Sleipnir C++ API
Loading...
Searching...
No Matches
Slice.hpp
Go to the documentation of this file.
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <concepts>
6#include <limits>
7#include <utility>
8
11
12namespace sleipnir {
13
14namespace slicing {
15
16struct none_t {};
17static inline constexpr none_t _;
18
19} // namespace slicing
20
22 public:
24 int start = 0;
25
27 int stop = 0;
28
30 int step = 1;
31
35 constexpr Slice() = default;
36
42 template <typename Stop>
43 requires std::same_as<Stop, slicing::none_t> ||
44 std::convertible_to<Stop, int>
45 constexpr Slice(Stop stop) // NOLINT
46 : Slice(slicing::_, std::move(stop), 1) {}
47
54 template <typename Start, typename Stop>
55 requires(std::same_as<Start, slicing::none_t> ||
56 std::convertible_to<Start, int>) &&
57 (std::same_as<Stop, slicing::none_t> ||
58 std::convertible_to<Stop, int>)
59 constexpr Slice(Start start, Stop stop)
60 : Slice(std::move(start), std::move(stop), 1) {}
61
69 template <typename Start, typename Stop, typename Step>
70 requires(std::same_as<Start, slicing::none_t> ||
71 std::convertible_to<Start, int>) &&
72 (std::same_as<Stop, slicing::none_t> ||
73 std::convertible_to<Stop, int>) &&
74 (std::same_as<Step, slicing::none_t> ||
75 std::convertible_to<Step, int>)
76 constexpr Slice(Start start, Stop stop, Step step) {
77 if constexpr (std::same_as<Step, slicing::none_t>) {
78 this->step = 1;
79 } else {
80 Assert(step != 0);
81
82 this->step = step;
83 }
84
85 // Avoid UB for step = -step if step is INT_MIN
86 if (this->step == std::numeric_limits<int>::min()) {
87 this->step = -std::numeric_limits<int>::max();
88 }
89
90 if constexpr (std::same_as<Start, slicing::none_t>) {
91 if (this->step < 0) {
92 this->start = std::numeric_limits<int>::max();
93 } else {
94 this->start = 0;
95 }
96 } else {
97 this->start = start;
98 }
99
100 if constexpr (std::same_as<Stop, slicing::none_t>) {
101 if (this->step < 0) {
102 this->stop = std::numeric_limits<int>::min();
103 } else {
104 this->stop = std::numeric_limits<int>::max();
105 }
106 } else {
107 this->stop = stop;
108 }
109 }
110
118 constexpr int Adjust(int length) {
119 Assert(step != 0);
120 Assert(step >= -std::numeric_limits<int>::max());
121
122 if (start < 0) {
123 start += length;
124
125 if (start < 0) {
126 start = (step < 0) ? -1 : 0;
127 }
128 } else if (start >= length) {
129 start = (step < 0) ? length - 1 : length;
130 }
131
132 if (stop < 0) {
133 stop += length;
134
135 if (stop < 0) {
136 stop = (step < 0) ? -1 : 0;
137 }
138 } else if (stop >= length) {
139 stop = (step < 0) ? length - 1 : length;
140 }
141
142 if (step < 0) {
143 if (stop < start) {
144 return (start - stop - 1) / -step + 1;
145 } else {
146 return 0;
147 }
148 } else {
149 if (start < stop) {
150 return (stop - start - 1) / step + 1;
151 } else {
152 return 0;
153 }
154 }
155 }
156};
157
158} // namespace sleipnir
#define Assert(condition)
Definition Assert.hpp:24
#define SLEIPNIR_DLLEXPORT
Definition SymbolExports.hpp:34
Definition Slice.hpp:21
constexpr Slice()=default
constexpr int Adjust(int length)
Definition Slice.hpp:118
constexpr Slice(Start start, Stop stop)
Definition Slice.hpp:59
constexpr Slice(Stop stop)
Definition Slice.hpp:45
constexpr Slice(Start start, Stop stop, Step step)
Definition Slice.hpp:76
static constexpr none_t _
Definition Slice.hpp:17
Definition Expression.hpp:18
Definition Slice.hpp:16