mkql_builtins_convert.cpp 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532
  1. #include "mkql_builtins_decimal.h" // Y_IGNORE
  2. #include <yql/essentials/public/udf/udf_value_builder.h>
  3. #include <util/generic/ylimits.h>
  4. #include <util/generic/ymath.h>
  5. #include <yql/essentials/minikql/mkql_string_util.h>
  6. #include <yql/essentials/types/binary_json/write.h>
  7. #include <yql/essentials/types/binary_json/read.h>
  8. namespace NKikimr {
  9. namespace NMiniKQL {
  10. namespace {
  11. template <typename TIn, typename TOut>
  12. struct TFloatToIntegralImpl {
  13. static constexpr TIn MinValue = static_cast<TIn>(std::numeric_limits<TOut>::min());
  14. static constexpr TIn MaxValue = std::is_same<TIn, double>::value ? MaxFloor<TOut>() : static_cast<TIn>(std::numeric_limits<TOut>::max());
  15. static NUdf::TUnboxedValuePod Do(TIn val) {
  16. switch (std::fpclassify(val)) {
  17. case FP_NORMAL:
  18. break;
  19. case FP_ZERO:
  20. case FP_SUBNORMAL:
  21. return NUdf::TUnboxedValuePod::Zero();
  22. default:
  23. return NUdf::TUnboxedValuePod();
  24. }
  25. if (val < MinValue || val > MaxValue) {
  26. return NUdf::TUnboxedValuePod();
  27. }
  28. return NUdf::TUnboxedValuePod(static_cast<TOut>(val));
  29. }
  30. #ifndef MKQL_DISABLE_CODEGEN
  31. static Value* Gen(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  32. {
  33. auto& context = ctx.Codegen.GetContext();
  34. auto& module = ctx.Codegen.GetModule();
  35. const auto val = GetterFor<TIn>(arg, context, block);
  36. const auto type = Type::getInt32Ty(context);
  37. const auto fnType = FunctionType::get(type, {val->getType()}, false);
  38. const auto name = std::is_same<TIn, float>() ? "MyFloatClassify" : "MyDoubleClassify";
  39. ctx.Codegen.AddGlobalMapping(name, reinterpret_cast<const void*>(static_cast<int(*)(TIn)>(&std::fpclassify)));
  40. const auto func = module.getOrInsertFunction(name, fnType).getCallee();
  41. const auto classify = CallInst::Create(fnType, func, {val}, "fpclassify", block);
  42. const auto none = BasicBlock::Create(context, "none", ctx.Func);
  43. const auto zero = BasicBlock::Create(context, "zero", ctx.Func);
  44. const auto good = BasicBlock::Create(context, "good", ctx.Func);
  45. const auto done = BasicBlock::Create(context, "done", ctx.Func);
  46. const auto result = PHINode::Create(arg->getType(), 3, "result", done);
  47. result->addIncoming(GetFalse(context), zero);
  48. result->addIncoming(ConstantInt::get(arg->getType(), 0), none);
  49. const auto choise = SwitchInst::Create(classify, none, 5, block);
  50. choise->addCase(ConstantInt::get(type, FP_NAN), none);
  51. choise->addCase(ConstantInt::get(type, FP_INFINITE), none);
  52. BranchInst::Create(done, none);
  53. choise->addCase(ConstantInt::get(type, FP_ZERO), zero);
  54. choise->addCase(ConstantInt::get(type, FP_SUBNORMAL), zero);
  55. BranchInst::Create(done, zero);
  56. choise->addCase(ConstantInt::get(type, FP_NORMAL), good);
  57. block = good;
  58. const auto less = CmpInst::Create(Instruction::FCmp, FCmpInst::FCMP_OLT, val, ConstantFP::get(val->getType(), MinValue), "less", block);
  59. const auto greater = CmpInst::Create(Instruction::FCmp, FCmpInst::FCMP_OGT, val, ConstantFP::get(val->getType(), MaxValue), "greater", block);
  60. const auto bad = BinaryOperator::CreateOr(less, greater, "or", block);
  61. const auto make = BasicBlock::Create(context, "make", ctx.Func);
  62. BranchInst::Create(none, make, bad, block);
  63. block = make;
  64. const auto cast = StaticCast<TIn, TOut>(val, context, block);
  65. const auto wide = SetterFor<TOut>(cast, context, block);
  66. result->addIncoming(wide, block);
  67. BranchInst::Create(done, block);
  68. block = done;
  69. return result;
  70. }
  71. #endif
  72. };
  73. template <typename TIn>
  74. struct TFloatToIntegralImpl<TIn, bool> {
  75. static NUdf::TUnboxedValuePod Do(TIn val) {
  76. switch (std::fpclassify(val)) {
  77. case FP_NORMAL:
  78. case FP_INFINITE:
  79. return NUdf::TUnboxedValuePod(true);
  80. break;
  81. case FP_ZERO:
  82. case FP_SUBNORMAL:
  83. return NUdf::TUnboxedValuePod(false);
  84. default:
  85. return NUdf::TUnboxedValuePod();
  86. }
  87. }
  88. #ifndef MKQL_DISABLE_CODEGEN
  89. static Value* Gen(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  90. {
  91. auto& context = ctx.Codegen.GetContext();
  92. auto& module = ctx.Codegen.GetModule();
  93. const auto val = GetterFor<TIn>(arg, context, block);
  94. const auto type = Type::getInt32Ty(context);
  95. const auto fnType = FunctionType::get(type, {val->getType()}, false);
  96. const auto name = std::is_same<TIn, float>() ? "MyFloatClassify" : "MyDoubleClassify";
  97. ctx.Codegen.AddGlobalMapping(name, reinterpret_cast<const void*>(static_cast<int(*)(TIn)>(&std::fpclassify)));
  98. const auto func = module.getOrInsertFunction(name, fnType).getCallee();
  99. const auto classify = CallInst::Create(fnType, func, {val}, "fpclassify", block);
  100. const auto none = BasicBlock::Create(context, "none", ctx.Func);
  101. const auto zero = BasicBlock::Create(context, "zero", ctx.Func);
  102. const auto good = BasicBlock::Create(context, "good", ctx.Func);
  103. const auto done = BasicBlock::Create(context, "done", ctx.Func);
  104. const auto result = PHINode::Create(arg->getType(), 3, "result", done);
  105. result->addIncoming(GetTrue(context), good);
  106. result->addIncoming(GetFalse(context), zero);
  107. result->addIncoming(ConstantInt::get(arg->getType(), 0), none);
  108. const auto choise = SwitchInst::Create(classify, none, 5, block);
  109. choise->addCase(ConstantInt::get(type, FP_NAN), none);
  110. BranchInst::Create(done, none);
  111. choise->addCase(ConstantInt::get(type, FP_ZERO), zero);
  112. choise->addCase(ConstantInt::get(type, FP_SUBNORMAL), zero);
  113. BranchInst::Create(done, zero);
  114. choise->addCase(ConstantInt::get(type, FP_INFINITE), good);
  115. choise->addCase(ConstantInt::get(type, FP_NORMAL), good);
  116. BranchInst::Create(done, good);
  117. block = done;
  118. return result;
  119. }
  120. #endif
  121. };
  122. template <typename TInput, typename TOutput>
  123. struct TFloatToIntegral : public TArithmeticConstraintsUnary<TInput, TOutput> {
  124. static_assert(std::is_floating_point<TInput>::value, "Input type must be floating point!");
  125. static_assert(std::is_integral<TOutput>::value, "Output type must be integral!");
  126. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg)
  127. {
  128. return TFloatToIntegralImpl<TInput, TOutput>::Do(arg.template Get<TInput>());
  129. }
  130. #ifndef MKQL_DISABLE_CODEGEN
  131. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  132. {
  133. return TFloatToIntegralImpl<TInput, TOutput>::Gen(arg, ctx, block);
  134. }
  135. #endif
  136. };
  137. #ifndef MKQL_DISABLE_CODEGEN
  138. Value* GenInBounds(Value* val, Constant* low, Constant* high, BasicBlock* block) {
  139. const auto lt = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SLE, val, high, "lt", block);
  140. const auto gt = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGE, val, low, "gt", block);
  141. const auto good = BinaryOperator::CreateAnd(lt, gt, "and", block);
  142. return good;
  143. }
  144. #endif
  145. template <typename TInput, typename TOutput,
  146. TOutput MaxVal = std::numeric_limits<TOutput>::max(),
  147. TOutput MinVal = std::numeric_limits<TOutput>::min()>
  148. struct TWideToShort : public TArithmeticConstraintsUnary<TInput, TOutput> {
  149. static_assert(std::is_integral_v<TInput>, "Input type must be integral!");
  150. static_assert(std::is_integral_v<TOutput>, "Output type must be integral!");
  151. static constexpr auto LowerBound = static_cast<TInput>(MinVal);
  152. static constexpr auto UpperBound = static_cast<TInput>(MaxVal);
  153. static constexpr bool SkipLower = std::is_unsigned_v<TInput> ||
  154. (sizeof(TInput) < sizeof(TOutput) && std::is_signed_v<TOutput>);
  155. static constexpr bool SkipUpper = sizeof(TInput) < sizeof(TOutput) ||
  156. (sizeof(TInput) == sizeof(TOutput) && std::is_signed_v<TInput> && std::is_unsigned_v<TOutput> && UpperBound < 0);
  157. static_assert(!(SkipLower && SkipUpper), "Only for cut input digits!");
  158. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg)
  159. {
  160. const auto val = arg.template Get<TInput>();
  161. const bool ok = (SkipLower || val >= LowerBound) && (SkipUpper || val <= UpperBound);
  162. return ok ? NUdf::TUnboxedValuePod(static_cast<TOutput>(val)) : NUdf::TUnboxedValuePod();
  163. }
  164. #ifndef MKQL_DISABLE_CODEGEN
  165. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  166. {
  167. auto& context = ctx.Codegen.GetContext();
  168. const auto val = GetterFor<TInput>(arg, context, block);
  169. const auto lb = ConstantInt::get(val->getType(), LowerBound);
  170. const auto ub = ConstantInt::get(val->getType(), UpperBound);
  171. const auto good = SkipLower ?
  172. CmpInst::Create(Instruction::ICmp, std::is_signed_v<TInput> ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE, val, ub, "ok", block):
  173. SkipUpper ?
  174. CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGE, val, lb, "ok", block):
  175. GenInBounds(val, lb, ub, block);
  176. const auto full = SetterFor<TOutput>(StaticCast<TInput, TOutput>(val, context, block), context, block);
  177. const auto res = SelectInst::Create(good, full, ConstantInt::get(arg->getType(), 0), "result", block);
  178. return res;
  179. }
  180. #endif
  181. };
  182. template <typename TInput, typename TOutput>
  183. struct TConvert : public TArithmeticConstraintsUnary<TInput, TOutput> {
  184. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  185. return NUdf::TUnboxedValuePod(static_cast<TOutput>(arg.template Get<TInput>()));
  186. }
  187. #ifndef MKQL_DISABLE_CODEGEN
  188. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  189. {
  190. auto& context = ctx.Codegen.GetContext();
  191. const auto val = GetterFor<TInput>(arg, context, block);
  192. const auto res = StaticCast<TInput, TOutput>(val, context, block);
  193. const auto wide = SetterFor<TOutput>(res, context, block);
  194. return wide;
  195. }
  196. #endif
  197. };
  198. template <typename TInput, typename TOutput, TOutput Multiplier>
  199. struct TScaleUp : public TArithmeticConstraintsUnary<TInput, TOutput> {
  200. static_assert(sizeof(TInput) < sizeof(TOutput), "Output should be wider than input.");
  201. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  202. return NUdf::TUnboxedValuePod(Multiplier * static_cast<TOutput>(arg.template Get<TInput>()));
  203. }
  204. #ifndef MKQL_DISABLE_CODEGEN
  205. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  206. {
  207. auto& context = ctx.Codegen.GetContext();
  208. const auto val = GetterFor<TInput>(arg, context, block);
  209. const auto cast = StaticCast<TInput, TOutput>(val, context, block);
  210. const auto mul = BinaryOperator::CreateMul(ConstantInt::get(cast->getType(), Multiplier), cast, "mul", block);
  211. const auto wide = SetterFor<TOutput>(mul, context, block);
  212. return wide;
  213. }
  214. #endif
  215. };
  216. template <typename TInput, typename TOutput>
  217. struct TDatetimeScale;
  218. template <>
  219. struct TDatetimeScale<ui16, ui32> {
  220. static constexpr ui32 Modifier = 86400U;
  221. };
  222. template <>
  223. struct TDatetimeScale<ui32, ui64> {
  224. static constexpr ui64 Modifier = 1000000ULL;
  225. };
  226. template <>
  227. struct TDatetimeScale<ui16, ui64> {
  228. static constexpr ui64 Modifier = 86400000000ULL;
  229. };
  230. template <typename TInput, typename TOutput>
  231. struct TBigDateScale;
  232. template <>
  233. struct TBigDateScale<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TDatetime64>> {
  234. static constexpr i64 Modifier = 86400LL;
  235. };
  236. template <>
  237. struct TBigDateScale<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDatetime64>> {
  238. static constexpr i64 Modifier = 86400LL;
  239. };
  240. template <>
  241. struct TBigDateScale<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDatetime>> {
  242. static constexpr i64 Modifier = 86400LL;
  243. };
  244. template <>
  245. struct TBigDateScale<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TTimestamp64>> {
  246. static constexpr i64 Modifier = 1000000LL;
  247. };
  248. template <>
  249. struct TBigDateScale<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTimestamp64>> {
  250. static constexpr i64 Modifier = 1000000LL;
  251. };
  252. template <>
  253. struct TBigDateScale<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTimestamp>> {
  254. static constexpr i64 Modifier = 1000000LL;
  255. };
  256. template <>
  257. struct TBigDateScale<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TTimestamp64>> {
  258. static constexpr i64 Modifier = 86400000000LL;
  259. };
  260. template <>
  261. struct TBigDateScale<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTimestamp64>> {
  262. static constexpr i64 Modifier = 86400000000LL;
  263. };
  264. template <>
  265. struct TBigDateScale<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTimestamp>> {
  266. static constexpr i64 Modifier = 86400000000LL;
  267. };
  268. template <typename TInput, typename TOutput>
  269. struct TBigDateScaleUp : public TArithmeticConstraintsUnary<typename TInput::TLayout, typename TOutput::TLayout> {
  270. static_assert(
  271. sizeof(typename TInput::TLayout) <= sizeof(typename TOutput::TLayout),
  272. "Output size should be greater or equal than input size.");
  273. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  274. return NUdf::TUnboxedValuePod(
  275. TBigDateScale<TInput, TOutput>::Modifier
  276. * static_cast<typename TOutput::TLayout>(arg.template Get<typename TInput::TLayout>()));
  277. }
  278. #ifndef MKQL_DISABLE_CODEGEN
  279. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  280. {
  281. auto& context = ctx.Codegen.GetContext();
  282. const auto val = GetterFor<typename TInput::TLayout>(arg, context, block);
  283. const auto cast = StaticCast<typename TInput::TLayout, typename TOutput::TLayout>(val, context, block);
  284. const auto mul = BinaryOperator::CreateMul(ConstantInt::get(cast->getType(), TBigDateScale<TInput, TOutput>::Modifier), cast, "mul", block);
  285. return SetterFor<typename TOutput::TLayout>(mul, context, block);
  286. }
  287. #endif
  288. };
  289. template <typename TInput, typename TOutput, i64 UpperBound>
  290. struct TBigDateToNarrowScaleUp : public TArithmeticConstraintsUnary<typename TInput::TLayout, typename TOutput::TLayout> {
  291. static_assert(
  292. sizeof(typename TInput::TLayout) <= sizeof(typename TOutput::TLayout),
  293. "Output size should be greater or equal than input size.");
  294. static_assert(std::is_signed_v<typename TInput::TLayout>, "Expect signed input type");
  295. static_assert(std::is_unsigned_v<typename TOutput::TLayout>, "Expect unsigned output type");
  296. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  297. auto result = TBigDateScale<TInput, TOutput>::Modifier * arg.template Get<typename TInput::TLayout>();
  298. if (result < 0 || result > UpperBound) {
  299. return NUdf::TUnboxedValuePod();
  300. }
  301. return NUdf::TUnboxedValuePod(static_cast<typename TOutput::TLayout>(result));
  302. }
  303. #ifndef MKQL_DISABLE_CODEGEN
  304. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  305. {
  306. auto& context = ctx.Codegen.GetContext();
  307. const auto val = GetterFor<typename TInput::TLayout>(arg, context, block);
  308. const auto val64 = StaticCast<typename TInput::TLayout, i64>(val, context, block);
  309. const auto mul = BinaryOperator::CreateMul(val64, ConstantInt::get(val64->getType(), TBigDateScale<TInput, TOutput>::Modifier), "mul", block);
  310. const auto cast = StaticCast<i64, typename TOutput::TLayout>(mul, context, block);
  311. const auto gt = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGE, val, ConstantInt::get(val->getType(), 0), "gt", block);
  312. const auto lt = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_ULE, mul, ConstantInt::get(mul->getType(), UpperBound), "lt", block);
  313. const auto good = BinaryOperator::CreateAnd(gt, lt, "and", block);
  314. const auto full = SetterFor<typename TOutput::TLayout>(cast, context, block);
  315. return SelectInst::Create(good, full, ConstantInt::get(arg->getType(), 0), "result", block);
  316. }
  317. #endif
  318. };
  319. template <typename TInput, typename TOutput>
  320. struct TNarrowToBigDateScaleDown : public TArithmeticConstraintsUnary<typename TInput::TLayout, typename TOutput::TLayout> {
  321. static_assert(
  322. sizeof(typename TInput::TLayout) >= sizeof(typename TOutput::TLayout),
  323. "Output size should be smaller or equal than input size.");
  324. static_assert(std::is_unsigned_v<typename TInput::TLayout>, "Input type must be unsigned.");
  325. static_assert(std::is_signed_v<typename TOutput::TLayout>, "Output type must be signed.");
  326. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  327. return NUdf::TUnboxedValuePod(static_cast<typename TOutput::TLayout>(
  328. arg.template Get<typename TInput::TLayout>() / TBigDateScale<TOutput, TInput>::Modifier));
  329. }
  330. #ifndef MKQL_DISABLE_CODEGEN
  331. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  332. {
  333. auto& context = ctx.Codegen.GetContext();
  334. const auto val = GetterFor<typename TInput::TLayout>(arg, context, block);
  335. const auto div = BinaryOperator::CreateUDiv(val, ConstantInt::get(val->getType(), TBigDateScale<TOutput, TInput>::Modifier), "div", block);
  336. const auto cast = StaticCast<typename TInput::TLayout, typename TOutput::TLayout>(div, context, block);
  337. return SetterFor<typename TOutput::TLayout>(cast, context, block);
  338. }
  339. #endif
  340. };
  341. template <typename TInput, typename TOutput>
  342. struct TBigDateScaleDown : public TArithmeticConstraintsUnary<typename TInput::TLayout, typename TOutput::TLayout> {
  343. static_assert(
  344. sizeof(typename TInput::TLayout) >= sizeof(typename TOutput::TLayout),
  345. "Output size should be smaller or equal than input size.");
  346. static_assert(
  347. std::is_signed_v<typename TInput::TLayout> &&
  348. std::is_signed_v<typename TOutput::TLayout>,
  349. "Only for signed layout types.");
  350. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  351. return NUdf::TUnboxedValuePod(static_cast<typename TOutput::TLayout>(
  352. arg.template Get<typename TInput::TLayout>() / TBigDateScale<TOutput, TInput>::Modifier));
  353. }
  354. #ifndef MKQL_DISABLE_CODEGEN
  355. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  356. {
  357. auto& context = ctx.Codegen.GetContext();
  358. const auto val = GetterFor<typename TInput::TLayout>(arg, context, block);
  359. const auto div = BinaryOperator::CreateSDiv(val, ConstantInt::get(val->getType(), TBigDateScale<TOutput, TInput>::Modifier), "div", block);
  360. const auto cast = StaticCast<typename TInput::TLayout, typename TOutput::TLayout>(div, context, block);
  361. return SetterFor<typename TOutput::TLayout>(cast, context, block);
  362. }
  363. #endif
  364. };
  365. template <typename TInput, typename TOutput, i64 UpperBound>
  366. struct TBigDateToNarrowScaleDown : public TArithmeticConstraintsUnary<typename TInput::TLayout, typename TOutput::TLayout> {
  367. static_assert(
  368. sizeof(typename TInput::TLayout) > sizeof(typename TOutput::TLayout),
  369. "Output size should be smaller than input size.");
  370. static_assert(std::is_same_v<i64, typename TInput::TLayout>, "Expect i64 input type");
  371. static_assert(std::is_unsigned_v<typename TOutput::TLayout>, "Expect unsigned output type");
  372. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  373. auto inputValue = arg.template Get<typename TInput::TLayout>();
  374. if (inputValue < 0) {
  375. return NUdf::TUnboxedValuePod();
  376. }
  377. auto result = inputValue / TBigDateScale<TOutput, TInput>::Modifier;
  378. if (result > UpperBound) {
  379. return NUdf::TUnboxedValuePod();
  380. }
  381. return NUdf::TUnboxedValuePod(static_cast<typename TOutput::TLayout>(result));
  382. }
  383. #ifndef MKQL_DISABLE_CODEGEN
  384. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  385. {
  386. auto& context = ctx.Codegen.GetContext();
  387. const auto val = GetterFor<typename TInput::TLayout>(arg, context, block);
  388. const auto div = BinaryOperator::CreateSDiv(val, ConstantInt::get(val->getType(), TBigDateScale<TOutput, TInput>::Modifier), "div", block);
  389. const auto gt = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGE, val, ConstantInt::get(val->getType(), 0), "gt", block);
  390. const auto lt = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SLE, div, ConstantInt::get(div->getType(), UpperBound), "lt", block);
  391. const auto good = BinaryOperator::CreateAnd(gt, lt, "and", block);
  392. const auto cast = StaticCast<typename TInput::TLayout, typename TOutput::TLayout>(div, context, block);
  393. const auto full = SetterFor<typename TOutput::TLayout>(cast, context, block);
  394. return SelectInst::Create(good, full, ConstantInt::get(arg->getType(), 0), "result", block);
  395. }
  396. #endif
  397. };
  398. template <typename TInput, typename TOutput, bool Tz = false>
  399. struct TDatetimeScaleUp : public TArithmeticConstraintsUnary<TInput, TOutput> {
  400. static_assert(sizeof(TInput) < sizeof(TOutput), "Output size should be wider than input size.");
  401. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  402. auto result = NUdf::TUnboxedValuePod(TDatetimeScale<TInput, TOutput>::Modifier * static_cast<TOutput>(arg.template Get<TInput>()));
  403. if constexpr (Tz) {
  404. result.SetTimezoneId(arg.GetTimezoneId());
  405. }
  406. return result;
  407. }
  408. #ifndef MKQL_DISABLE_CODEGEN
  409. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  410. {
  411. auto& context = ctx.Codegen.GetContext();
  412. const auto val = GetterFor<TInput>(arg, context, block);
  413. const auto cast = StaticCast<TInput, TOutput>(val, context, block);
  414. const auto mul = BinaryOperator::CreateMul(ConstantInt::get(cast->getType(), TDatetimeScale<TInput, TOutput>::Modifier), cast, "mul", block);
  415. const auto wide = SetterFor<TOutput>(mul, context, block);
  416. if constexpr (Tz) {
  417. const uint64_t init[] = {0ULL, 0xFFFFULL};
  418. const auto mask = ConstantInt::get(arg->getType(), APInt(128, 2, init));
  419. const auto tzid = BinaryOperator::CreateAnd(arg, mask, "tzid", block);
  420. const auto full = BinaryOperator::CreateOr(wide, tzid, "full", block);
  421. return full;
  422. } else {
  423. return wide;
  424. }
  425. }
  426. #endif
  427. };
  428. template <typename TInput, typename TOutput, bool Tz = false>
  429. struct TDatetimeScaleDown : public TArithmeticConstraintsUnary<TInput, TOutput> {
  430. static_assert(sizeof(TInput) > sizeof(TOutput), "Output size should be narrower than input size.");
  431. static_assert(std::is_unsigned_v<TInput> && std::is_unsigned_v<TOutput>, "Only for unsigned.");
  432. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  433. auto result = NUdf::TUnboxedValuePod(static_cast<TOutput>(arg.template Get<TInput>() / TDatetimeScale<TOutput, TInput>::Modifier));
  434. if constexpr (Tz) {
  435. result.SetTimezoneId(arg.GetTimezoneId());
  436. }
  437. return result;
  438. }
  439. #ifndef MKQL_DISABLE_CODEGEN
  440. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  441. {
  442. auto& context = ctx.Codegen.GetContext();
  443. const auto val = GetterFor<TInput>(arg, context, block);
  444. const auto div = BinaryOperator::CreateUDiv(val, ConstantInt::get(val->getType(), TDatetimeScale<TOutput, TInput>::Modifier), "div", block);
  445. const auto cast = StaticCast<TInput, TOutput>(div, context, block);
  446. const auto wide = SetterFor<TOutput>(cast, context, block);
  447. if constexpr (Tz) {
  448. const uint64_t init[] = {0ULL, 0xFFFFULL};
  449. const auto mask = ConstantInt::get(arg->getType(), APInt(128, 2, init));
  450. const auto tzid = BinaryOperator::CreateAnd(arg, mask, "tzid", block);
  451. const auto full = BinaryOperator::CreateOr(wide, tzid, "full", block);
  452. return full;
  453. } else {
  454. return wide;
  455. }
  456. }
  457. #endif
  458. };
  459. template <typename TInput, typename TOutput, bool Tz>
  460. using TDatetimeRescale = std::conditional_t<sizeof(TInput) < sizeof(TOutput),
  461. TDatetimeScaleUp<TInput, TOutput, Tz>,
  462. TDatetimeScaleDown<TInput, TOutput, Tz>
  463. >;
  464. template <bool Cleanup = false>
  465. struct TDatetimeTzStub {
  466. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  467. auto result = arg;
  468. if (Cleanup) {
  469. result.SetTimezoneId(0);
  470. }
  471. return result;
  472. }
  473. #ifndef MKQL_DISABLE_CODEGEN
  474. static Value* Generate(Value* arg, const TCodegenContext&, BasicBlock*& block)
  475. {
  476. if constexpr (Cleanup) {
  477. const uint64_t init[] = {0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFF0000ULL};
  478. const auto mask = ConstantInt::get(arg->getType(), APInt(128, 2, init));
  479. return BinaryOperator::CreateAnd(arg, mask, "clean", block);
  480. } else {
  481. return arg;
  482. }
  483. }
  484. #endif
  485. };
  486. struct TStringConvert {
  487. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg)
  488. {
  489. Y_DEBUG_ABORT_UNLESS(!arg.IsBoxed(), "Expected unboxed arg in String::Convert()");
  490. return arg; // handle optional args as well
  491. }
  492. #ifndef MKQL_DISABLE_CODEGEN
  493. static Value* Generate(Value* arg, const TCodegenContext&, BasicBlock*&)
  494. {
  495. return arg;
  496. }
  497. #endif
  498. };
  499. NUdf::TUnboxedValuePod JsonToJsonDocument(const NUdf::TUnboxedValuePod value) {
  500. auto maybeBinaryJson = NKikimr::NBinaryJson::SerializeToBinaryJson(value.AsStringRef());
  501. if (std::holds_alternative<TString>(maybeBinaryJson)) {
  502. // JSON parse error happened, return NULL
  503. return NUdf::TUnboxedValuePod();
  504. }
  505. const auto& binaryJson = std::get<NKikimr::NBinaryJson::TBinaryJson>(maybeBinaryJson);
  506. return MakeString(TStringBuf(binaryJson.Data(), binaryJson.Size()));
  507. }
  508. struct TJsonToJsonDocumentConvert {
  509. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg)
  510. {
  511. return JsonToJsonDocument(arg);
  512. }
  513. #ifndef MKQL_DISABLE_CODEGEN
  514. static Value* Generate(Value* json, const TCodegenContext& ctx, BasicBlock*& block)
  515. {
  516. auto& context = ctx.Codegen.GetContext();
  517. const auto functionAddress = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(JsonToJsonDocument));
  518. const auto functionType = FunctionType::get(json->getType(), {json->getType()}, /* isVarArg */ false);
  519. const auto functionPtr = CastInst::Create(Instruction::IntToPtr, functionAddress, PointerType::getUnqual(functionType), "func", block);
  520. return CallInst::Create(functionType, functionPtr, {json}, "jsonToJsonDocument", block);
  521. }
  522. #endif
  523. };
  524. NUdf::TUnboxedValuePod JsonDocumentToJson(const NUdf::TUnboxedValuePod value) {
  525. auto json = NKikimr::NBinaryJson::SerializeToJson(value.AsStringRef());
  526. return MakeString(json);
  527. }
  528. struct TJsonDocumentToJsonConvert {
  529. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg)
  530. {
  531. return JsonDocumentToJson(arg);
  532. }
  533. #ifndef MKQL_DISABLE_CODEGEN
  534. static Value* Generate(Value* jsonDocument, const TCodegenContext& ctx, BasicBlock*& block)
  535. {
  536. auto& context = ctx.Codegen.GetContext();
  537. const auto functionAddress = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(JsonDocumentToJson));
  538. const auto functionType = FunctionType::get(jsonDocument->getType(), {jsonDocument->getType()}, /* isVarArg */ false);
  539. const auto functionPtr = CastInst::Create(Instruction::IntToPtr, functionAddress, PointerType::getUnqual(functionType), "func", block);
  540. return CallInst::Create(functionType, functionPtr, {jsonDocument}, "jsonDocumentToJson", block);
  541. }
  542. #endif
  543. };
  544. }
  545. namespace NDecimal {
  546. template <typename TInput>
  547. struct TConvertFromIntegral {
  548. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  549. return NUdf::TUnboxedValuePod(NYql::NDecimal::TInt128(arg.Get<TInput>()));
  550. }
  551. #ifndef MKQL_DISABLE_CODEGEN
  552. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  553. {
  554. const auto val = GetterFor<TInput>(arg, ctx.Codegen.GetContext(), block);
  555. const auto ext = CastInst::Create(std::is_signed<TInput>() ? Instruction::SExt : Instruction::ZExt, val, arg->getType(), "ext", block);
  556. return SetterForInt128(ext, block);
  557. }
  558. #endif
  559. static_assert(std::is_arithmetic<TInput>::value, "Input type must be arithmetic!");
  560. };
  561. template <typename TOutput>
  562. struct TConvertToIntegral {
  563. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  564. const auto v = arg.GetInt128();
  565. return v >= std::numeric_limits<TOutput>::min() && v <= std::numeric_limits<TOutput>::max() ?
  566. NUdf::TUnboxedValuePod(static_cast<TOutput>(arg.GetInt128())) : NUdf::TUnboxedValuePod();
  567. }
  568. #ifndef MKQL_DISABLE_CODEGEN
  569. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  570. {
  571. auto& context = ctx.Codegen.GetContext();
  572. const auto val = GetterForInt128(arg, block);
  573. const auto cut = CastInst::Create(Instruction::Trunc, val, GetTypeFor<TOutput>(context), "cut", block);
  574. const auto full = SetterFor<TOutput>(cut, context, block);
  575. const auto good = GenInBounds<true>(val, GenConstant(std::numeric_limits<TOutput>::min(), context), GenConstant(std::numeric_limits<TOutput>::max(), context), block);
  576. const auto res = SelectInst::Create(good, full, ConstantInt::get(arg->getType(), 0), "result", block);
  577. return res;
  578. }
  579. #endif
  580. static_assert(std::is_arithmetic<TOutput>::value, "Output type must be arithmetic!");
  581. };
  582. template<typename TOutput, ui8 Scale>
  583. TOutput GetFP(NYql::NDecimal::TInt128 v);
  584. template<>
  585. float GetFP<float, 0>(NYql::NDecimal::TInt128 v) {
  586. return static_cast<float>(v);
  587. }
  588. template<>
  589. double GetFP<double, 0>(NYql::NDecimal::TInt128 v) {
  590. return static_cast<double>(v);
  591. }
  592. template<typename TOutput, ui8 Scale>
  593. TOutput GetFP(NYql::NDecimal::TInt128 v) {
  594. if (v % 10)
  595. return static_cast<TOutput>(v) / static_cast<TOutput>(NYql::NDecimal::GetDivider<Scale>());
  596. else
  597. return GetFP<TOutput, Scale - 1>(v / 10);
  598. }
  599. #ifndef MKQL_DISABLE_CODEGEN
  600. template<typename TOutput, ui8 Scale>
  601. void GenFP(PHINode* result, Value* val, const TCodegenContext& ctx, BasicBlock* done, BasicBlock*& block);
  602. template<>
  603. void GenFP<float, 0>(PHINode* result, Value* val, const TCodegenContext& ctx, BasicBlock* done, BasicBlock*& block) {
  604. const auto cast = CastInst::Create(Instruction::SIToFP, val, GetTypeFor<float>(ctx.Codegen.GetContext()), "cast", block);
  605. result->addIncoming(cast, block);
  606. BranchInst::Create(done, block);
  607. }
  608. template<>
  609. void GenFP<double, 0>(PHINode* result, Value* val, const TCodegenContext& ctx, BasicBlock* done, BasicBlock*& block) {
  610. const auto cast = CastInst::Create(Instruction::SIToFP, val, GetTypeFor<double>(ctx.Codegen.GetContext()), "cast", block);
  611. result->addIncoming(cast, block);
  612. BranchInst::Create(done, block);
  613. }
  614. template<typename TOutput, ui8 Scale>
  615. void GenFP(PHINode* result, Value* val, const TCodegenContext& ctx, BasicBlock* done, BasicBlock*& block) {
  616. auto& context = ctx.Codegen.GetContext();
  617. const auto& str = ToString(Scale);
  618. const auto stop = BasicBlock::Create(context, (TString("stop_") += str).c_str(), ctx.Func);
  619. const auto step = BasicBlock::Create(context, (TString("step_") += str).c_str(), ctx.Func);
  620. const auto ten = ConstantInt::get(val->getType(), 10U);
  621. const auto rem = BinaryOperator::CreateSRem(val, ten, "rem", block);
  622. const auto nul = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, rem, ConstantInt::get(val->getType(), 0U), "nul", block);
  623. BranchInst::Create(step, stop, nul, block);
  624. block = stop;
  625. const auto cast = CastInst::Create(Instruction::SIToFP, val, GetTypeFor<TOutput>(ctx.Codegen.GetContext()), "cast", block);
  626. const auto divf = BinaryOperator::CreateFDiv(cast, ConstantFP::get(GetTypeFor<TOutput>(context), static_cast<TOutput>(NYql::NDecimal::GetDivider<Scale>())), "divf", block);
  627. result->addIncoming(divf, block);
  628. BranchInst::Create(done, block);
  629. block = step;
  630. const auto div = BinaryOperator::CreateSDiv(val, ten, "div", block);
  631. GenFP<TOutput, Scale - 1>(result, div, ctx, done, block);
  632. }
  633. #endif
  634. template <typename TOutput, ui8 Scale>
  635. struct TToFP {
  636. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  637. const auto v = arg.GetInt128();
  638. if (v == +NYql::NDecimal::Inf())
  639. return NUdf::TUnboxedValuePod(+std::numeric_limits<TOutput>::infinity());
  640. if (v == -NYql::NDecimal::Inf())
  641. return NUdf::TUnboxedValuePod(-std::numeric_limits<TOutput>::infinity());
  642. if (v == +NYql::NDecimal::Nan())
  643. return NUdf::TUnboxedValuePod(+std::numeric_limits<TOutput>::quiet_NaN());
  644. if (v == -NYql::NDecimal::Nan())
  645. return NUdf::TUnboxedValuePod(-std::numeric_limits<TOutput>::quiet_NaN());
  646. return NUdf::TUnboxedValuePod(GetFP<TOutput, Scale>(v));
  647. }
  648. #ifndef MKQL_DISABLE_CODEGEN
  649. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  650. {
  651. auto& context = ctx.Codegen.GetContext();
  652. const auto val = GetterForInt128(arg, block);
  653. const auto pnan = BasicBlock::Create(context, "pnan", ctx.Func);
  654. const auto pinf = BasicBlock::Create(context, "pinf", ctx.Func);
  655. const auto mnan = BasicBlock::Create(context, "mnan", ctx.Func);
  656. const auto minf = BasicBlock::Create(context, "minf", ctx.Func);
  657. const auto norm = BasicBlock::Create(context, "norm", ctx.Func);
  658. const auto done = BasicBlock::Create(context, "done", ctx.Func);
  659. const auto result = PHINode::Create(GetTypeFor<TOutput>(context), 5U + Scale, "result", done);
  660. const auto choise = SwitchInst::Create(val, norm, 4U, block);
  661. choise->addCase(GenConstant(+NYql::NDecimal::Nan(), context), pnan);
  662. choise->addCase(GenConstant(-NYql::NDecimal::Nan(), context), mnan);
  663. choise->addCase(GenConstant(+NYql::NDecimal::Inf(), context), pinf);
  664. choise->addCase(GenConstant(-NYql::NDecimal::Inf(), context), minf);
  665. block = pnan;
  666. result->addIncoming(ConstantFP::get(GetTypeFor<TOutput>(context), +std::numeric_limits<TOutput>::quiet_NaN()), block);
  667. BranchInst::Create(done, block);
  668. block = mnan;
  669. result->addIncoming(ConstantFP::get(GetTypeFor<TOutput>(context), -std::numeric_limits<TOutput>::quiet_NaN()), block);
  670. BranchInst::Create(done, block);
  671. block = pinf;
  672. result->addIncoming(ConstantFP::get(GetTypeFor<TOutput>(context), +std::numeric_limits<TOutput>::infinity()), block);
  673. BranchInst::Create(done, block);
  674. block = minf;
  675. result->addIncoming(ConstantFP::get(GetTypeFor<TOutput>(context), -std::numeric_limits<TOutput>::infinity()), block);
  676. BranchInst::Create(done, block);
  677. block = norm;
  678. GenFP<TOutput, Scale>(result, val, ctx, done, block);
  679. block = done;
  680. return SetterFor<TOutput>(result, context, block);
  681. }
  682. #endif
  683. static_assert(std::is_floating_point<TOutput>::value, "Output type must be floating point!");
  684. static_assert(Scale <= NYql::NDecimal::MaxPrecision, "Too large scale!");
  685. };
  686. template <ui8 Scale> using TToFloat = TToFP<float, Scale>;
  687. template <ui8 Scale> using TToDouble = TToFP<double, Scale>;
  688. template <ui8 Scale>
  689. struct TScaleUp {
  690. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  691. return NUdf::TUnboxedValuePod(NYql::NDecimal::Mul(arg.GetInt128(), NYql::NDecimal::GetDivider<Scale>()));
  692. }
  693. #ifndef MKQL_DISABLE_CODEGEN
  694. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  695. {
  696. auto& context = ctx.Codegen.GetContext();
  697. const auto val = GetterForInt128(arg, block);
  698. const auto mul = BinaryOperator::CreateMul(val, GenConstant(NYql::NDecimal::GetDivider<Scale>(), context), "mul", block);
  699. const auto res = SelectInst::Create(GenIsNormal(val, context, block), mul, val, "result", block);
  700. return SetterForInt128(res, block);
  701. }
  702. #endif
  703. static_assert(Scale <= NYql::NDecimal::MaxPrecision, "Too large scale!");
  704. };
  705. template <ui8 Scale>
  706. struct TScaleDown {
  707. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  708. return NUdf::TUnboxedValuePod(NYql::NDecimal::Div(arg.GetInt128(), NYql::NDecimal::GetDivider<Scale>()));
  709. }
  710. #ifndef MKQL_DISABLE_CODEGEN
  711. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  712. {
  713. auto& context = ctx.Codegen.GetContext();
  714. const auto val = GetterForInt128(arg, block);
  715. const auto divider = GenConstant(NYql::NDecimal::GetDivider<Scale>() >> 1, context);
  716. const auto nul = ConstantInt::get(val->getType(), 0);
  717. const auto one = ConstantInt::get(val->getType(), 1);
  718. const auto div = BinaryOperator::CreateSDiv(val, divider, "div", block);
  719. const auto ashr = BinaryOperator::CreateAShr(div, one, "ashr", block);
  720. const auto bit = CastInst::Create(Instruction::Trunc, div, Type::getInt1Ty(context), "bit", block);
  721. const auto done = BasicBlock::Create(context, "done", ctx.Func);
  722. const auto round = BasicBlock::Create(context, "round", ctx.Func);
  723. const auto result = PHINode::Create(val->getType(), 2, "result", done);
  724. result->addIncoming(ashr, block);
  725. BranchInst::Create(round, done, bit, block);
  726. block = round;
  727. const auto mod = BinaryOperator::CreateSRem(val, divider, "mod", block);
  728. const auto zero = CmpInst::Create(Instruction::ICmp, FCmpInst::ICMP_EQ, mod, nul, "zero", block);
  729. const auto plus = CmpInst::Create(Instruction::ICmp, FCmpInst::ICMP_SGT, mod, nul, "plus", block);
  730. const auto test = CastInst::Create(Instruction::Trunc, ashr, Type::getInt1Ty(context), "test", block);
  731. const auto even = BinaryOperator::CreateAnd(test, zero, "even", block);
  732. const auto up = BinaryOperator::CreateOr(plus, even, "up", block);
  733. const auto inc = BinaryOperator::CreateAdd(ashr, one, "inc", block);
  734. const auto rounded = SelectInst::Create(up, inc, ashr, "result", block);
  735. result->addIncoming(rounded, block);
  736. BranchInst::Create(done, block);
  737. block = done;
  738. const auto res = SelectInst::Create(GenIsNormal(val, context, block), result, val, "res", block);
  739. return SetterForInt128(res, block);
  740. }
  741. #endif
  742. static_assert(Scale <= NYql::NDecimal::MaxPrecision, "Too large scale!");
  743. };
  744. template <ui8 Precision>
  745. struct TCheckBounds {
  746. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) {
  747. const auto v = arg.GetInt128();
  748. using namespace NYql::NDecimal;
  749. if (IsNormal<Precision>(v))
  750. return arg;
  751. return NUdf::TUnboxedValuePod(IsNan(v) ? Nan() : (v > 0 ? +Inf() : -Inf()));
  752. }
  753. #ifndef MKQL_DISABLE_CODEGEN
  754. static Value* Generate(Value* arg, const TCodegenContext& ctx, BasicBlock*& block)
  755. {
  756. auto& context = ctx.Codegen.GetContext();
  757. const auto val = GetterForInt128(arg, block);
  758. const auto& bounds = GenBounds<Precision>(context);
  759. const auto good = GenInBounds(val, bounds.first, bounds.second, block);
  760. const auto nan = GenIsNonComparable(val, context, block);
  761. const auto plus = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGT, val, ConstantInt::get(val->getType(), 0), "plus", block);
  762. const auto inf = SelectInst::Create(plus, GetDecimalPlusInf(context), GetDecimalMinusInf(context), "inf", block);
  763. const auto bad = SelectInst::Create(nan, GetDecimalNan(context), inf, "bad", block);
  764. const auto res = SelectInst::Create(good, arg, SetterForInt128(bad, block), "res", block);
  765. return res;
  766. }
  767. #endif
  768. static_assert(Precision <= NYql::NDecimal::MaxPrecision, "Too large precision!");
  769. };
  770. }
  771. namespace {
  772. constexpr auto convert = "Convert";
  773. constexpr auto integral = "ToIntegral";
  774. constexpr auto decimal = "ToDecimal";
  775. template <typename TInput, typename TOutput>
  776. void RegisterConvert(IBuiltinFunctionRegistry& registry) {
  777. RegisterFunctionUnOpt<TInput, TOutput, TConvert, TUnaryArgsOpt>(registry, convert);
  778. }
  779. template <typename TInput, typename TOutput>
  780. void RegisterStringConvert(IBuiltinFunctionRegistry& registry) {
  781. RegisterFunctionOpt<TInput, TOutput, TStringConvert, TUnaryArgsOpt>(registry, convert);
  782. }
  783. template <typename TOutput>
  784. void RegisterIntegralCasts(IBuiltinFunctionRegistry& registry) {
  785. RegisterConvert<NUdf::TDataType<i8>, TOutput>(registry);
  786. RegisterConvert<NUdf::TDataType<ui8>, TOutput>(registry);
  787. RegisterConvert<NUdf::TDataType<i16>, TOutput>(registry);
  788. RegisterConvert<NUdf::TDataType<ui16>, TOutput>(registry);
  789. RegisterConvert<NUdf::TDataType<i32>, TOutput>(registry);
  790. RegisterConvert<NUdf::TDataType<ui32>, TOutput>(registry);
  791. RegisterConvert<NUdf::TDataType<i64>, TOutput>(registry);
  792. RegisterConvert<NUdf::TDataType<ui64>, TOutput>(registry);
  793. RegisterConvert<NUdf::TDataType<bool>, TOutput>(registry);
  794. }
  795. template <typename TInput>
  796. void RegisterDecimalConvertFromIntegral(IBuiltinFunctionRegistry& registry) {
  797. RegisterFunctionOpt<NUdf::TDataType<TInput>, NUdf::TDataType<NUdf::TDecimal>, NDecimal::TConvertFromIntegral<TInput>, TUnaryArgsOpt>(registry, decimal);
  798. }
  799. template <typename TOutput>
  800. void RegisterDecimalConvertToIntegral(IBuiltinFunctionRegistry& registry) {
  801. RegisterFunctionImpl<NDecimal::TConvertToIntegral<TOutput>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDecimal>, NUdf::TDataType<TOutput>, false>, TUnaryStub>(registry, integral);
  802. RegisterFunctionImpl<NDecimal::TConvertToIntegral<TOutput>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDecimal>, NUdf::TDataType<TOutput>, true>, TUnaryWrap>(registry, integral);
  803. }
  804. void RegisterDecimalConvert(IBuiltinFunctionRegistry& registry) {
  805. RegisterDecimalConvertFromIntegral<i8>(registry);
  806. RegisterDecimalConvertFromIntegral<ui8>(registry);
  807. RegisterDecimalConvertFromIntegral<i16>(registry);
  808. RegisterDecimalConvertFromIntegral<ui16>(registry);
  809. RegisterDecimalConvertFromIntegral<i32>(registry);
  810. RegisterDecimalConvertFromIntegral<ui32>(registry);
  811. RegisterDecimalConvertFromIntegral<i64>(registry);
  812. RegisterDecimalConvertFromIntegral<ui64>(registry);
  813. RegisterDecimalConvertToIntegral<i8>(registry);
  814. RegisterDecimalConvertToIntegral<ui8>(registry);
  815. RegisterDecimalConvertToIntegral<i16>(registry);
  816. RegisterDecimalConvertToIntegral<ui16>(registry);
  817. RegisterDecimalConvertToIntegral<i32>(registry);
  818. RegisterDecimalConvertToIntegral<ui32>(registry);
  819. RegisterDecimalConvertToIntegral<i64>(registry);
  820. RegisterDecimalConvertToIntegral<ui64>(registry);
  821. NDecimal::RegisterUnaryFunctionForAllPrecisions<NDecimal::TScaleUp, TUnaryArgsOpt>(registry, "ScaleUp_");
  822. NDecimal::RegisterUnaryFunctionForAllPrecisions<NDecimal::TScaleDown, TUnaryArgsOpt>(registry, "ScaleDown_");
  823. NDecimal::RegisterUnaryFunctionForAllPrecisions<NDecimal::TCheckBounds, TUnaryArgsOpt>(registry, "CheckBounds_");
  824. NDecimal::RegisterCastFunctionForAllPrecisions<NDecimal::TToFloat, TUnaryArgsOpt, NUdf::TDataType<float>>(registry, "ToFloat_");
  825. NDecimal::RegisterCastFunctionForAllPrecisions<NDecimal::TToDouble, TUnaryArgsOpt, NUdf::TDataType<double>>(registry, "ToDouble_");
  826. }
  827. template <typename TOutput>
  828. void RegisterRealCasts(IBuiltinFunctionRegistry& registry) {
  829. RegisterConvert<NUdf::TDataType<float>, TOutput>(registry);
  830. RegisterConvert<NUdf::TDataType<double>, TOutput>(registry);
  831. }
  832. template <typename TInput, typename TOutput>
  833. void RegisterRealToIntegralCastsImpl(IBuiltinFunctionRegistry& registry) {
  834. RegisterFunctionImpl<TFloatToIntegral<typename TInput::TLayout, typename TOutput::TLayout>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, false>, TUnaryStub>(registry, integral);
  835. RegisterFunctionImpl<TFloatToIntegral<typename TInput::TLayout, typename TOutput::TLayout>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, true>, TUnaryWrap>(registry, integral);
  836. }
  837. template <typename TInput>
  838. void RegisterRealToIntegralCasts(IBuiltinFunctionRegistry& registry) {
  839. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<i8>>(registry);
  840. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<ui8>>(registry);
  841. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<i16>>(registry);
  842. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<ui16>>(registry);
  843. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<i32>>(registry);
  844. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<ui32>>(registry);
  845. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<i64>>(registry);
  846. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<ui64>>(registry);
  847. RegisterRealToIntegralCastsImpl<TInput, NUdf::TDataType<bool>>(registry);
  848. }
  849. template <typename TInput, typename TOutput>
  850. void RegisterWideToShortCastsImpl(IBuiltinFunctionRegistry& registry) {
  851. RegisterFunctionImpl<TWideToShort<typename TInput::TLayout, typename TOutput::TLayout>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, false>, TUnaryStub>(registry, integral);
  852. RegisterFunctionImpl<TWideToShort<typename TInput::TLayout, typename TOutput::TLayout>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, true>, TUnaryWrap>(registry, integral);
  853. }
  854. template <typename TInput, typename TOutput,
  855. typename TInput::TLayout UpperBound = std::numeric_limits<typename TInput::TLayout>::max()>
  856. void RegisterWideToDateCastsImpl(IBuiltinFunctionRegistry& registry) {
  857. RegisterFunctionImpl<TWideToShort<typename TInput::TLayout, typename TOutput::TLayout, UpperBound>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, false>, TUnaryStub>(registry, integral);
  858. RegisterFunctionImpl<TWideToShort<typename TInput::TLayout, typename TOutput::TLayout, UpperBound>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, true>, TUnaryWrap>(registry, integral);
  859. }
  860. template <typename TInput, typename TOutput,
  861. typename TInput::TLayout UpperBound = std::numeric_limits<typename TInput::TLayout>::max(),
  862. typename TInput::TLayout LowerBound = std::numeric_limits<typename TInput::TLayout>::min()>
  863. void RegisterWideToBigDateCastsImpl(IBuiltinFunctionRegistry& registry) {
  864. RegisterFunctionImpl<TWideToShort<typename TInput::TLayout, typename TOutput::TLayout, UpperBound, LowerBound>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, false>, TUnaryStub>(registry, integral);
  865. RegisterFunctionImpl<TWideToShort<typename TInput::TLayout, typename TOutput::TLayout, UpperBound, LowerBound>, TUnaryArgsWithNullableResultOpt<TInput, TOutput, true>, TUnaryWrap>(registry, integral);
  866. }
  867. void RegisterWideToIntervalCasts(IBuiltinFunctionRegistry& registry) {
  868. constexpr auto TimestampLimit = static_cast<i64>(NUdf::MAX_TIMESTAMP - 1ULL);
  869. RegisterFunctionImpl<TWideToShort<i64, i64, TimestampLimit, -TimestampLimit>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TInterval>, false>, TUnaryStub>(registry, integral);
  870. RegisterFunctionImpl<TWideToShort<i64, i64, TimestampLimit, -TimestampLimit>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TInterval>, true>, TUnaryWrap>(registry, integral);
  871. RegisterFunctionImpl<TWideToShort<ui64, i64, TimestampLimit>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TInterval>, false>, TUnaryStub>(registry, integral);
  872. RegisterFunctionImpl<TWideToShort<ui64, i64, TimestampLimit>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TInterval>, true>, TUnaryWrap>(registry, integral);
  873. }
  874. template <typename TInput>
  875. void RegisterWideToUnsignedCasts(IBuiltinFunctionRegistry& registry) {
  876. RegisterWideToShortCastsImpl<TInput, NUdf::TDataType<ui8>>(registry);
  877. RegisterWideToShortCastsImpl<TInput, NUdf::TDataType<ui16>>(registry);
  878. RegisterWideToShortCastsImpl<TInput, NUdf::TDataType<ui32>>(registry);
  879. RegisterWideToShortCastsImpl<TInput, NUdf::TDataType<ui64>>(registry);
  880. }
  881. void RegisterWideToDateCasts(IBuiltinFunctionRegistry& registry) {
  882. RegisterWideToDateCastsImpl<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TDate>>(registry);
  883. RegisterWideToDateCastsImpl<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TDate>>(registry);
  884. RegisterWideToDateCastsImpl<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>(registry);
  885. RegisterWideToDateCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>(registry);
  886. RegisterWideToDateCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>(registry);
  887. RegisterWideToDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>(registry);
  888. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>(registry);
  889. RegisterWideToDateCastsImpl<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TTzDate>>(registry);
  890. RegisterWideToDateCastsImpl<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TTzDate>>(registry);
  891. RegisterWideToDateCastsImpl<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TTzDate>, NUdf::MAX_DATE - 1U>(registry);
  892. RegisterWideToDateCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TTzDate>, NUdf::MAX_DATE - 1U>(registry);
  893. RegisterWideToDateCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TTzDate>, NUdf::MAX_DATE - 1U>(registry);
  894. RegisterWideToDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TTzDate>, NUdf::MAX_DATE - 1U>(registry);
  895. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TTzDate>, NUdf::MAX_DATE - 1U>(registry);
  896. }
  897. void RegisterWideToDatetimeCasts(IBuiltinFunctionRegistry& registry) {
  898. RegisterWideToDateCastsImpl<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  899. RegisterWideToDateCastsImpl<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  900. RegisterWideToDateCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  901. RegisterWideToDateCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TDatetime>, NUdf::MAX_DATETIME - 1U>(registry);
  902. RegisterWideToDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TDatetime>, NUdf::MAX_DATETIME - 1U>(registry);
  903. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TDatetime>, NUdf::MAX_DATETIME - 1U>(registry);
  904. RegisterWideToDateCastsImpl<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  905. RegisterWideToDateCastsImpl<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  906. RegisterWideToDateCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  907. RegisterWideToDateCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::MAX_DATETIME - 1U>(registry);
  908. RegisterWideToDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::MAX_DATETIME - 1U>(registry);
  909. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::MAX_DATETIME - 1U>(registry);
  910. }
  911. void RegisterWideToBigDateCasts(IBuiltinFunctionRegistry& registry) {
  912. RegisterWideToBigDateCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TDate32>, NUdf::MAX_DATE32, NUdf::MIN_DATE32>(registry);
  913. RegisterWideToBigDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TDate32>, NUdf::MAX_DATE32, NUdf::MIN_DATE32>(registry);
  914. RegisterWideToDateCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TDate32>, NUdf::MAX_DATE32>(registry);
  915. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TDate32>, NUdf::MAX_DATE32>(registry);
  916. RegisterWideToBigDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TDatetime64>, NUdf::MAX_DATETIME64, NUdf::MIN_DATETIME64>(registry);
  917. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TDatetime64>, NUdf::MAX_DATETIME64>(registry);
  918. RegisterWideToBigDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TTimestamp64>, NUdf::MAX_TIMESTAMP64, NUdf::MIN_TIMESTAMP64>(registry);
  919. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TTimestamp64>, NUdf::MAX_TIMESTAMP64>(registry);
  920. RegisterWideToBigDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TInterval64>, NUdf::MAX_INTERVAL64, -NUdf::MAX_INTERVAL64>(registry);
  921. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TInterval64>, NUdf::MAX_INTERVAL64>(registry);
  922. }
  923. void RegisterWideToTimestampCasts(IBuiltinFunctionRegistry& registry) {
  924. RegisterWideToDateCastsImpl<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  925. RegisterWideToDateCastsImpl<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  926. RegisterWideToDateCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  927. RegisterWideToDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TTimestamp>, NUdf::MAX_TIMESTAMP - 1U>(registry);
  928. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TTimestamp>, NUdf::MAX_TIMESTAMP - 1U>(registry);
  929. RegisterWideToDateCastsImpl<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  930. RegisterWideToDateCastsImpl<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  931. RegisterWideToDateCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  932. RegisterWideToDateCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::MAX_TIMESTAMP - 1U>(registry);
  933. RegisterWideToDateCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::MAX_TIMESTAMP - 1U>(registry);
  934. }
  935. void RegisterWideToShortIntegralCasts(IBuiltinFunctionRegistry& registry) {
  936. RegisterWideToUnsignedCasts<NUdf::TDataType<i8>>(registry);
  937. RegisterWideToUnsignedCasts<NUdf::TDataType<i16>>(registry);
  938. RegisterWideToUnsignedCasts<NUdf::TDataType<i32>>(registry);
  939. RegisterWideToUnsignedCasts<NUdf::TDataType<i64>>(registry);
  940. RegisterWideToShortCastsImpl<NUdf::TDataType<ui8>, NUdf::TDataType<i8>>(registry);
  941. RegisterWideToShortCastsImpl<NUdf::TDataType<i16>, NUdf::TDataType<i8>>(registry);
  942. RegisterWideToShortCastsImpl<NUdf::TDataType<ui16>, NUdf::TDataType<i8>>(registry);
  943. RegisterWideToShortCastsImpl<NUdf::TDataType<ui16>, NUdf::TDataType<ui8>>(registry);
  944. RegisterWideToShortCastsImpl<NUdf::TDataType<ui16>, NUdf::TDataType<i16>>(registry);
  945. RegisterWideToShortCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<i8>>(registry);
  946. RegisterWideToShortCastsImpl<NUdf::TDataType<i32>, NUdf::TDataType<i16>>(registry);
  947. RegisterWideToShortCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<i8>>(registry);
  948. RegisterWideToShortCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<ui8>>(registry);
  949. RegisterWideToShortCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<i16>>(registry);
  950. RegisterWideToShortCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<ui16>>(registry);
  951. RegisterWideToShortCastsImpl<NUdf::TDataType<ui32>, NUdf::TDataType<i32>>(registry);
  952. RegisterWideToShortCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<i8>>(registry);
  953. RegisterWideToShortCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<i16>>(registry);
  954. RegisterWideToShortCastsImpl<NUdf::TDataType<i64>, NUdf::TDataType<i32>>(registry);
  955. RegisterWideToShortCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<i8>>(registry);
  956. RegisterWideToShortCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<ui8>>(registry);
  957. RegisterWideToShortCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<i16>>(registry);
  958. RegisterWideToShortCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<ui16>>(registry);
  959. RegisterWideToShortCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<i32>>(registry);
  960. RegisterWideToShortCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<ui32>>(registry);
  961. RegisterWideToShortCastsImpl<NUdf::TDataType<ui64>, NUdf::TDataType<i64>>(registry);
  962. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<i8>>(registry);
  963. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<ui8>>(registry);
  964. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<i16>>(registry);
  965. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<i8>>(registry);
  966. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<ui8>>(registry);
  967. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<i16>>(registry);
  968. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<i8>>(registry);
  969. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<ui8>>(registry);
  970. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<i16>>(registry);
  971. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<ui16>>(registry);
  972. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<i32>>(registry);
  973. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<i8>>(registry);
  974. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<ui8>>(registry);
  975. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<i16>>(registry);
  976. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<ui16>>(registry);
  977. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<i32>>(registry);
  978. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<i8>>(registry);
  979. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<ui8>>(registry);
  980. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<i16>>(registry);
  981. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<ui16>>(registry);
  982. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<i32>>(registry);
  983. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<ui32>>(registry);
  984. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<i8>>(registry);
  985. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<ui8>>(registry);
  986. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<i16>>(registry);
  987. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<ui16>>(registry);
  988. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<i32>>(registry);
  989. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<ui32>>(registry);
  990. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TInterval>, NUdf::TDataType<i8>>(registry);
  991. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TInterval>, NUdf::TDataType<i16>>(registry);
  992. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TInterval>, NUdf::TDataType<i32>>(registry);
  993. RegisterWideToUnsignedCasts<NUdf::TDataType<NUdf::TInterval>>(registry);
  994. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<i8>>(registry);
  995. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<i16>>(registry);
  996. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<i32>>(registry);
  997. RegisterWideToUnsignedCasts<NUdf::TDataType<NUdf::TDate32>>(registry);
  998. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<i8>>(registry);
  999. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<i16>>(registry);
  1000. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<i32>>(registry);
  1001. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<i64>>(registry);
  1002. RegisterWideToUnsignedCasts<NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1003. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<i8>>(registry);
  1004. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<i16>>(registry);
  1005. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<i32>>(registry);
  1006. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<i64>>(registry);
  1007. RegisterWideToUnsignedCasts<NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1008. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<i8>>(registry);
  1009. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<i16>>(registry);
  1010. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<i32>>(registry);
  1011. RegisterWideToShortCastsImpl<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<i64>>(registry);
  1012. RegisterWideToUnsignedCasts<NUdf::TDataType<NUdf::TInterval64>>(registry);
  1013. RegisterWideToDateCasts(registry);
  1014. RegisterWideToBigDateCasts(registry);
  1015. RegisterWideToDatetimeCasts(registry);
  1016. RegisterWideToTimestampCasts(registry);
  1017. RegisterWideToIntervalCasts(registry);
  1018. }
  1019. template <typename TDate>
  1020. void RegisterFromDateConvert(IBuiltinFunctionRegistry& registry) {
  1021. RegisterConvert<TDate, NUdf::TDataType<i8>>(registry);
  1022. RegisterConvert<TDate, NUdf::TDataType<ui8>>(registry);
  1023. RegisterConvert<TDate, NUdf::TDataType<i16>>(registry);
  1024. RegisterConvert<TDate, NUdf::TDataType<ui16>>(registry);
  1025. RegisterConvert<TDate, NUdf::TDataType<i32>>(registry);
  1026. RegisterConvert<TDate, NUdf::TDataType<ui32>>(registry);
  1027. RegisterConvert<TDate, NUdf::TDataType<i64>>(registry);
  1028. RegisterConvert<TDate, NUdf::TDataType<ui64>>(registry);
  1029. RegisterConvert<TDate, NUdf::TDataType<float>>(registry);
  1030. RegisterConvert<TDate, NUdf::TDataType<double>>(registry);
  1031. }
  1032. void RegisterToDateConvert(IBuiltinFunctionRegistry& registry) {
  1033. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TDate>>(registry);
  1034. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TTzDate>>(registry);
  1035. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  1036. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  1037. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  1038. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  1039. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1040. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  1041. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1042. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  1043. RegisterConvert<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1044. RegisterConvert<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  1045. RegisterConvert<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TInterval>>(registry);
  1046. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TInterval>>(registry);
  1047. RegisterConvert<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TInterval>>(registry);
  1048. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TInterval>>(registry);
  1049. RegisterConvert<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TInterval>>(registry);
  1050. RegisterConvert<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TInterval>>(registry);
  1051. // Unsafe converts from layout type. Only for internal use.
  1052. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TDate>>(registry);
  1053. RegisterConvert<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  1054. RegisterConvert<NUdf::TDataType<ui64>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1055. RegisterConvert<NUdf::TDataType<i64>, NUdf::TDataType<NUdf::TInterval>>(registry);
  1056. }
  1057. void RegisterToBigDateConvert(IBuiltinFunctionRegistry& registry) {
  1058. RegisterConvert<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TDate32>>(registry);
  1059. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TDate32>>(registry);
  1060. RegisterConvert<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TDate32>>(registry);
  1061. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TDate32>>(registry);
  1062. RegisterConvert<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1063. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1064. RegisterConvert<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1065. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1066. RegisterConvert<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1067. RegisterConvert<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1068. RegisterConvert<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1069. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1070. RegisterConvert<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1071. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1072. RegisterConvert<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1073. RegisterConvert<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1074. RegisterConvert<NUdf::TDataType<i8>, NUdf::TDataType<NUdf::TInterval64>>(registry);
  1075. RegisterConvert<NUdf::TDataType<ui8>, NUdf::TDataType<NUdf::TInterval64>>(registry);
  1076. RegisterConvert<NUdf::TDataType<i16>, NUdf::TDataType<NUdf::TInterval64>>(registry);
  1077. RegisterConvert<NUdf::TDataType<ui16>, NUdf::TDataType<NUdf::TInterval64>>(registry);
  1078. RegisterConvert<NUdf::TDataType<i32>, NUdf::TDataType<NUdf::TInterval64>>(registry);
  1079. RegisterConvert<NUdf::TDataType<ui32>, NUdf::TDataType<NUdf::TInterval64>>(registry);
  1080. }
  1081. template <typename TInput, typename TOutput>
  1082. void RegisterBigDateScaleUp(IBuiltinFunctionRegistry& registry) {
  1083. RegisterFunctionImpl<TBigDateScaleUp<TInput, TOutput>, TUnaryArgsOpt<TInput, TOutput, false>, TUnaryStub>(registry, convert);
  1084. RegisterFunctionImpl<TBigDateScaleUp<TInput, TOutput>, TUnaryArgsOpt<TInput, TOutput, true>, TUnaryWrap>(registry, convert);
  1085. }
  1086. template <typename TInput, typename TOutput>
  1087. void RegisterBigDateScaleDown(IBuiltinFunctionRegistry& registry) {
  1088. RegisterFunctionImpl<TBigDateScaleDown<TInput, TOutput>, TUnaryArgsOpt<TInput, TOutput, false>, TUnaryStub>(registry, convert);
  1089. RegisterFunctionImpl<TBigDateScaleDown<TInput, TOutput>, TUnaryArgsOpt<TInput, TOutput, true>, TUnaryWrap>(registry, convert);
  1090. }
  1091. void RegisterBigDateRescale(IBuiltinFunctionRegistry& registry) {
  1092. RegisterBigDateScaleUp<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1093. RegisterBigDateScaleUp<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1094. RegisterBigDateScaleUp<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1095. RegisterBigDateScaleDown<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TDate32>>(registry);
  1096. RegisterBigDateScaleDown<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDate32>>(registry);
  1097. RegisterBigDateScaleDown<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1098. }
  1099. void RegisterNarrowToBigDateCasts(IBuiltinFunctionRegistry& registry) {
  1100. RegisterConvert<NUdf::TDataType<NUdf::TInterval>, NUdf::TDataType<NUdf::TInterval64>>(registry);
  1101. RegisterConvert<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1102. RegisterConvert<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1103. RegisterConvert<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TDate32>>(registry);
  1104. RegisterBigDateScaleUp<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1105. RegisterBigDateScaleUp<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1106. RegisterBigDateScaleUp<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1107. RegisterFunctionImpl<TNarrowToBigDateScaleDown<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TDate32>>, TUnaryArgsOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TDate32>, false>, TUnaryStub>(registry, convert);
  1108. RegisterFunctionImpl<TNarrowToBigDateScaleDown<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TDate32>>, TUnaryArgsOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TDate32>, true>, TUnaryWrap>(registry, convert);
  1109. RegisterFunctionImpl<TNarrowToBigDateScaleDown<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDate32>>, TUnaryArgsOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDate32>, false>, TUnaryStub>(registry, convert);
  1110. RegisterFunctionImpl<TNarrowToBigDateScaleDown<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDate32>>, TUnaryArgsOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDate32>, true>, TUnaryWrap>(registry, convert);
  1111. RegisterFunctionImpl<TNarrowToBigDateScaleDown<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDatetime64>>, TUnaryArgsOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDatetime64>, false>, TUnaryStub>(registry, convert);
  1112. RegisterFunctionImpl<TNarrowToBigDateScaleDown<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDatetime64>>, TUnaryArgsOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDatetime64>, true>, TUnaryWrap>(registry, convert);
  1113. }
  1114. void RegisterBigDateToNarrowCasts(IBuiltinFunctionRegistry& registry) {
  1115. RegisterFunctionImpl<TWideToShort<i32, ui16, NYql::NUdf::MAX_DATE - 1U>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDate>, false>, TUnaryStub>(registry, integral);
  1116. RegisterFunctionImpl<TWideToShort<i32, ui16, NYql::NUdf::MAX_DATE - 1U>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDate>, true>, TUnaryWrap>(registry, integral);
  1117. RegisterFunctionImpl<TWideToShort<i64, ui32, NYql::NUdf::MAX_DATETIME - 1U>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TDatetime>, false>, TUnaryStub>(registry, integral);
  1118. RegisterFunctionImpl<TWideToShort<i64, ui32, NYql::NUdf::MAX_DATETIME - 1U>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TDatetime>, true>, TUnaryWrap>(registry, integral);
  1119. RegisterFunctionImpl<TWideToShort<i64, ui64, NYql::NUdf::MAX_TIMESTAMP - 1ULL>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TTimestamp>, false>, TUnaryStub>(registry, integral);
  1120. RegisterFunctionImpl<TWideToShort<i64, ui64, NYql::NUdf::MAX_TIMESTAMP - 1ULL>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TTimestamp>, true>, TUnaryWrap>(registry, integral);
  1121. constexpr auto TimestampLimit = static_cast<i64>(NUdf::MAX_TIMESTAMP - 1ULL);
  1122. RegisterFunctionImpl<TWideToShort<i64, i64, TimestampLimit, -TimestampLimit>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval>, false>, TUnaryStub>(registry, integral);
  1123. RegisterFunctionImpl<TWideToShort<i64, i64, TimestampLimit, -TimestampLimit>, TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval>, true>, TUnaryWrap>(registry, integral);
  1124. RegisterFunctionImpl<
  1125. TBigDateToNarrowScaleUp<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDatetime>, NUdf::MAX_DATETIME - 1U>,
  1126. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDatetime>, false>,
  1127. TUnaryStub>(registry, integral);
  1128. RegisterFunctionImpl<
  1129. TBigDateToNarrowScaleUp<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDatetime>, NUdf::MAX_DATETIME - 1U>,
  1130. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TDatetime>, true>,
  1131. TUnaryWrap>(registry, integral);
  1132. RegisterFunctionImpl<
  1133. TBigDateToNarrowScaleUp<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTimestamp>, NUdf::MAX_TIMESTAMP - 1U>,
  1134. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTimestamp>, false>,
  1135. TUnaryStub>(registry, integral);
  1136. RegisterFunctionImpl<
  1137. TBigDateToNarrowScaleUp<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTimestamp>, NUdf::MAX_TIMESTAMP - 1U>,
  1138. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTimestamp>, true>,
  1139. TUnaryWrap>(registry, integral);
  1140. RegisterFunctionImpl<
  1141. TBigDateToNarrowScaleUp<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTimestamp>, NUdf::MAX_TIMESTAMP - 1U>,
  1142. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTimestamp>, false>,
  1143. TUnaryStub>(registry, integral);
  1144. RegisterFunctionImpl<
  1145. TBigDateToNarrowScaleUp<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTimestamp>, NUdf::MAX_TIMESTAMP - 1U>,
  1146. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTimestamp>, true>,
  1147. TUnaryWrap>(registry, integral);
  1148. RegisterFunctionImpl<
  1149. TBigDateToNarrowScaleDown<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>,
  1150. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TDate>, false>,
  1151. TUnaryStub>(registry, integral);
  1152. RegisterFunctionImpl<
  1153. TBigDateToNarrowScaleDown<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>,
  1154. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TDate>, true>,
  1155. TUnaryWrap>(registry, integral);
  1156. RegisterFunctionImpl<
  1157. TBigDateToNarrowScaleDown<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>,
  1158. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDate>, false>,
  1159. TUnaryStub>(registry, integral);
  1160. RegisterFunctionImpl<
  1161. TBigDateToNarrowScaleDown<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDate>, NUdf::MAX_DATE - 1U>,
  1162. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDate>, true>,
  1163. TUnaryWrap>(registry, integral);
  1164. RegisterFunctionImpl<
  1165. TBigDateToNarrowScaleDown<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDatetime>, NUdf::MAX_DATETIME - 1U>,
  1166. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDatetime>, false>,
  1167. TUnaryStub>(registry, integral);
  1168. RegisterFunctionImpl<
  1169. TBigDateToNarrowScaleDown<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDatetime>, NUdf::MAX_DATETIME - 1U>,
  1170. TUnaryArgsWithNullableResultOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TDatetime>, true>,
  1171. TUnaryWrap>(registry, integral);
  1172. }
  1173. template <typename TInput, typename TOutput, bool Tz = false>
  1174. void RegisterRescaleOpt(IBuiltinFunctionRegistry& registry) {
  1175. RegisterFunctionImpl<TDatetimeRescale<typename TInput::TLayout, typename TOutput::TLayout, Tz>, TUnaryArgsOpt<TInput, TOutput, false>, TUnaryStub>(registry, convert);
  1176. RegisterFunctionImpl<TDatetimeRescale<typename TInput::TLayout, typename TOutput::TLayout, Tz>, TUnaryArgsOpt<TInput, TOutput, true>, TUnaryWrap>(registry, convert);
  1177. }
  1178. void RegisterDatetimeRescale(IBuiltinFunctionRegistry& registry) {
  1179. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  1180. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  1181. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1182. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  1183. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1184. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  1185. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TDate>>(registry);
  1186. RegisterRescaleOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TTzDate>>(registry);
  1187. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDate>>(registry);
  1188. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TTzDate>>(registry);
  1189. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  1190. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  1191. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  1192. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TTzDatetime>, true>(registry);
  1193. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1194. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TTzTimestamp>, true>(registry);
  1195. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TDate>>(registry);
  1196. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TTzDate>, true>(registry);
  1197. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1198. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TTzTimestamp>, true>(registry);
  1199. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TDate>>(registry);
  1200. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTzDate>, true>(registry);
  1201. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TDatetime>>(registry);
  1202. RegisterRescaleOpt<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTzDatetime>, true>(registry);
  1203. }
  1204. template <typename TInput, typename TOutput, bool Clenup = false>
  1205. void RegisterTzDateimeOpt(IBuiltinFunctionRegistry& registry) {
  1206. RegisterFunctionImpl<TDatetimeTzStub<Clenup>, TUnaryArgsOpt<TInput, TOutput, false>, TUnaryStub>(registry, convert);
  1207. RegisterFunctionImpl<TDatetimeTzStub<Clenup>, TUnaryArgsOpt<TInput, TOutput, true>, TUnaryWrap>(registry, convert);
  1208. }
  1209. void RegisterTzDateimeConvert(IBuiltinFunctionRegistry& registry) {
  1210. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TTzDate>>(registry);
  1211. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  1212. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  1213. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TDate>, true>(registry);
  1214. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TDatetime>, true>(registry);
  1215. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTimestamp>, true>(registry);
  1216. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TTzDate32>>(registry);
  1217. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TTzDatetime64>>(registry);
  1218. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TTzTimestamp64>>(registry);
  1219. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TDate32>, true>(registry);
  1220. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TDatetime64>, true>(registry);
  1221. RegisterTzDateimeOpt<NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TTimestamp64>, true>(registry);
  1222. }
  1223. void RegisterJsonDocumentConvert(IBuiltinFunctionRegistry& registry) {
  1224. // String/Utf8 -> JsonDocument and JsonDocument -> String/Utf8 conversions. TStringConvert is used as a placeholder because
  1225. // actual conversions are handled by ValueFromString and ValueToString in mkql_type_ops.cpp
  1226. RegisterFunctionOpt<NUdf::TDataType<char*>, NUdf::TDataType<NUdf::TJsonDocument>, TStringConvert, TUnaryArgsOpt>(registry, convert);
  1227. RegisterFunctionOpt<NUdf::TDataType<NUdf::TUtf8>, NUdf::TDataType<NUdf::TJsonDocument>, TStringConvert, TUnaryArgsOpt>(registry, convert);
  1228. RegisterFunctionOpt<NUdf::TDataType<NUdf::TJsonDocument>, NUdf::TDataType<char*>, TStringConvert, TUnaryArgsOpt>(registry, convert);
  1229. RegisterFunctionOpt<NUdf::TDataType<NUdf::TJsonDocument>, NUdf::TDataType<NUdf::TUtf8>, TStringConvert, TUnaryArgsOpt>(registry, convert);
  1230. // Json -> JsonDocument and JsonDocument -> Json conversions
  1231. RegisterFunctionOpt<NUdf::TDataType<NUdf::TJson>, NUdf::TDataType<NUdf::TJsonDocument>, TJsonToJsonDocumentConvert, TUnaryArgsOpt>(registry, convert);
  1232. RegisterFunctionOpt<NUdf::TDataType<NUdf::TJsonDocument>, NUdf::TDataType<NUdf::TJson>, TJsonDocumentToJsonConvert, TUnaryArgsOpt>(registry, convert);
  1233. }
  1234. }
  1235. void RegisterConvert(IBuiltinFunctionRegistry& registry) {
  1236. RegisterIntegralCasts<NUdf::TDataType<i32>>(registry);
  1237. RegisterIntegralCasts<NUdf::TDataType<ui32>>(registry);
  1238. RegisterIntegralCasts<NUdf::TDataType<i64>>(registry);
  1239. RegisterIntegralCasts<NUdf::TDataType<ui64>>(registry);
  1240. RegisterIntegralCasts<NUdf::TDataType<ui8>>(registry);
  1241. RegisterIntegralCasts<NUdf::TDataType<i8>>(registry);
  1242. RegisterIntegralCasts<NUdf::TDataType<ui16>>(registry);
  1243. RegisterIntegralCasts<NUdf::TDataType<i16>>(registry);
  1244. RegisterIntegralCasts<NUdf::TDataType<bool>>(registry);
  1245. RegisterIntegralCasts<NUdf::TDataType<float>>(registry);
  1246. RegisterIntegralCasts<NUdf::TDataType<double>>(registry);
  1247. RegisterWideToShortIntegralCasts(registry);
  1248. RegisterRealCasts<NUdf::TDataType<i8>>(registry);
  1249. RegisterRealCasts<NUdf::TDataType<ui8>>(registry);
  1250. RegisterRealCasts<NUdf::TDataType<i16>>(registry);
  1251. RegisterRealCasts<NUdf::TDataType<ui16>>(registry);
  1252. RegisterRealCasts<NUdf::TDataType<i32>>(registry);
  1253. RegisterRealCasts<NUdf::TDataType<ui32>>(registry);
  1254. RegisterRealCasts<NUdf::TDataType<i64>>(registry);
  1255. RegisterRealCasts<NUdf::TDataType<ui64>>(registry);
  1256. RegisterRealCasts<NUdf::TDataType<float>>(registry);
  1257. RegisterRealCasts<NUdf::TDataType<double>>(registry);
  1258. RegisterRealToIntegralCasts<NUdf::TDataType<float>>(registry);
  1259. RegisterRealToIntegralCasts<NUdf::TDataType<double>>(registry);
  1260. RegisterStringConvert<NUdf::TDataType<char*>, NUdf::TDataType<char*>>(registry);
  1261. RegisterStringConvert<NUdf::TDataType<NUdf::TUtf8>, NUdf::TDataType<char*>>(registry);
  1262. RegisterStringConvert<NUdf::TDataType<NUdf::TYson>, NUdf::TDataType<char*>>(registry);
  1263. RegisterStringConvert<NUdf::TDataType<NUdf::TJson>, NUdf::TDataType<char*>>(registry);
  1264. RegisterStringConvert<NUdf::TDataType<NUdf::TJson>, NUdf::TDataType<NUdf::TUtf8>>(registry);
  1265. RegisterFromDateConvert<NUdf::TDataType<NUdf::TDate>>(registry);
  1266. RegisterFromDateConvert<NUdf::TDataType<NUdf::TDatetime>>(registry);
  1267. RegisterFromDateConvert<NUdf::TDataType<NUdf::TTimestamp>>(registry);
  1268. RegisterFromDateConvert<NUdf::TDataType<NUdf::TInterval>>(registry);
  1269. RegisterFromDateConvert<NUdf::TDataType<NUdf::TTzDate>>(registry);
  1270. RegisterFromDateConvert<NUdf::TDataType<NUdf::TTzDatetime>>(registry);
  1271. RegisterFromDateConvert<NUdf::TDataType<NUdf::TTzTimestamp>>(registry);
  1272. RegisterFromDateConvert<NUdf::TDataType<NUdf::TDate32>>(registry);
  1273. RegisterFromDateConvert<NUdf::TDataType<NUdf::TDatetime64>>(registry);
  1274. RegisterFromDateConvert<NUdf::TDataType<NUdf::TTimestamp64>>(registry);
  1275. RegisterFromDateConvert<NUdf::TDataType<NUdf::TInterval64>>(registry);
  1276. RegisterTzDateimeConvert(registry);
  1277. RegisterDatetimeRescale(registry);
  1278. RegisterToDateConvert(registry);
  1279. RegisterToBigDateConvert(registry);
  1280. RegisterBigDateRescale(registry);
  1281. RegisterNarrowToBigDateCasts(registry);
  1282. RegisterBigDateToNarrowCasts(registry);
  1283. RegisterDecimalConvert(registry);
  1284. RegisterJsonDocumentConvert(registry);
  1285. }
  1286. } // namespace NMiniKQL
  1287. } // namespace NKikimr