From 5c68ef00ac0d20a829abc60ceda79d8dc4bae73f Mon Sep 17 00:00:00 2001 From: lyken Date: Fri, 23 Aug 2024 10:00:51 +0800 Subject: [PATCH] core/irrt: refactor out slice::indices and range::len --- nac3core/irrt/irrt/slice.hpp | 102 ++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/nac3core/irrt/irrt/slice.hpp b/nac3core/irrt/irrt/slice.hpp index c064924b..98d3646d 100644 --- a/nac3core/irrt/irrt/slice.hpp +++ b/nac3core/irrt/irrt/slice.hpp @@ -7,6 +7,19 @@ namespace { +namespace range +{ +template T len(T start, T stop, T step) +{ + // Reference: https://github.com/python/cpython/blob/9dbd12375561a393eaec4b21ee4ac568a407cdb0/Objects/rangeobject.c#L933 + if (step > 0 && start < stop) + return 1 + (stop - 1 - start) / step; + else if (step < 0 && start > stop) + return 1 + (start - 1 - stop) / (-step); + else + return 0; +} +} // namespace range /** * @brief A Python range. @@ -22,15 +35,8 @@ template struct Range */ template T len() { - // Reference: https://github.com/python/cpython/blob/9dbd12375561a393eaec4b21ee4ac568a407cdb0/Objects/rangeobject.c#L933 debug_assert(SizeT, step != 0); - - if (step > 0 && start < stop) - return 1 + (stop - 1 - start) / step; - else if (step < 0 && start > stop) - return 1 + (start - 1 - stop) / (-step); - else - return 0; + return range::len(start, stop, step); } }; @@ -75,6 +81,50 @@ template T resolve_index_in_length(T length, T index) return -1; } } + +/** + * @brief Resolve a slice as a range. + * + * In Python, this would be `range(*slice(start, stop, step).indices(length))`. + */ +template +void indices(bool start_defined, T start, bool stop_defined, T stop, bool step_defined, T step, T length, + T *range_start, T *range_stop, T *range_step) +{ + // Reference: https://github.com/python/cpython/blob/main/Objects/sliceobject.c#L388 + *range_step = step_defined ? step : 1; + bool step_is_negative = *range_step < 0; + + T lower, upper; + if (step_is_negative) + { + lower = -1; + upper = length - 1; + } + else + { + lower = 0; + upper = length; + } + + if (start_defined) + { + *range_start = start < 0 ? max(lower, start + length) : min(upper, start); + } + else + { + *range_start = step_is_negative ? upper : lower; + } + + if (stop_defined) + { + *range_stop = stop < 0 ? max(lower, stop + length) : min(upper, stop); + } + else + { + *range_stop = step_is_negative ? lower : upper; + } +} } // namespace slice /** @@ -132,40 +182,8 @@ template struct Slice debug_assert(SizeT, length >= 0); Range result; - - result.step = step_defined ? step : 1; - bool step_is_negative = result.step < 0; - - T lower, upper; - if (step_is_negative) - { - lower = -1; - upper = length - 1; - } - else - { - lower = 0; - upper = length; - } - - if (start_defined) - { - result.start = start < 0 ? max(lower, start + length) : min(upper, start); - } - else - { - result.start = step_is_negative ? upper : lower; - } - - if (stop_defined) - { - result.stop = stop < 0 ? max(lower, stop + length) : min(upper, stop); - } - else - { - result.stop = step_is_negative ? lower : upper; - } - + slice::indices(start_defined, start, stop_defined, stop, step_defined, step, length, &result.start, + &result.stop, &result.step); return result; }