forked from M-Labs/nac3
core/irrt: refactor out slice::indices and range::len
This commit is contained in:
parent
3782791323
commit
5c68ef00ac
|
@ -7,6 +7,19 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
namespace range
|
||||
{
|
||||
template <typename T> 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 <typename T> struct Range
|
|||
*/
|
||||
template <typename SizeT> 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 <typename T> 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 <typename T>
|
||||
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 <typename T> struct Slice
|
|||
debug_assert(SizeT, length >= 0);
|
||||
|
||||
Range<T> 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue