#pragma once #include #include #include #include #include #include #include #include namespace NKikimr::NMiniKQL { using NYql::NWindow::EDirection; // clang-format off template using TNextWiderSigned = std::conditional_t>>; // clang-format on enum class EInfBoundary { Left, Right, }; // InfBoundary == Right -> [boundary, +inf) // InfBoundary == Left -> (-inf, boundary] template Y_FORCE_INLINE constexpr bool IsBelongToInterval(EInfBoundary InfBoundary, EDirection dir, T from, U delta, T x) { Y_DEBUG_ABORT_UNLESS(delta >= 0); if constexpr (std::is_floating_point_v) { Y_DEBUG_ABORT_UNLESS(!std::isnan(from)); Y_DEBUG_ABORT_UNLESS(!std::isnan(x)); } if constexpr (std::is_floating_point_v) { Y_DEBUG_ABORT_UNLESS(!std::isnan(delta)); } if constexpr (std::is_floating_point_v || std::is_floating_point_v) { const auto b = (dir == EDirection::Following) ? (from + delta) : (from - delta); Y_DEBUG_ABORT_UNLESS(!std::isnan(b)); if (InfBoundary == EInfBoundary::Right) { return x >= b; } else { return x <= b; } } else { static_assert(std::is_integral_v, "T must be integral or floating"); static_assert(!std::is_same_v, "bool is not supported"); static_assert(std::is_integral_v, "U must be integral or floating"); static_assert(!std::is_same_v, "U is not supported"); static_assert(sizeof(T) == sizeof(i8) || sizeof(T) == sizeof(i16) || sizeof(T) == sizeof(i32) || sizeof(T) == sizeof(i64), "Only 8/16/32/64-bit integers are supported"); static_assert(sizeof(U) == sizeof(i8) || sizeof(U) == sizeof(i16) || sizeof(U) == sizeof(i32) || sizeof(U) == sizeof(i64), "Only 8/16/32/64-bit integers are supported"); using TW = TNextWiderSigned; using UW = TNextWiderSigned; const auto wf = static_cast(from); const auto wd = static_cast(delta); const auto wx = static_cast(x); const auto b = (dir == EDirection::Following) ? (wf + wd) : (wf - wd); if (InfBoundary == EInfBoundary::Right) { return wx >= b; // [b, +inf) } else { return wx <= b; // (-inf, b] } } } Y_FORCE_INLINE constexpr bool IsBelongToInterval(EInfBoundary infBoundary, EDirection dir, NYql::NDecimal::TInt128 from, NYql::NDecimal::TInt128 delta, NYql::NDecimal::TInt128 x, ui8 precision) { Y_DEBUG_ABORT_UNLESS(NYql::NDecimal::IsNormal(delta)); Y_DEBUG_ABORT_UNLESS(NYql::NDecimal::IsComparable(x)); Y_DEBUG_ABORT_UNLESS(NYql::NDecimal::IsComparable(from)); const auto b = (dir == EDirection::Following) ? NYql::NDecimal::Add(from, delta, precision) : NYql::NDecimal::Sub(from, delta, precision); Y_DEBUG_ABORT_UNLESS(NYql::NDecimal::IsComparable(b)); if (infBoundary == EInfBoundary::Right) { return NYql::NDecimal::IsGreaterOrEqual(x, b); } else { return NYql::NDecimal::IsLessOrEqual(x, b); } } } // namespace NKikimr::NMiniKQL