Sleipnir C++ API
Loading...
Searching...
No Matches
slice.hpp
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <concepts>
6#include <limits>
7#include <utility>
8
9#include "sleipnir/util/assert.hpp"
10#include "sleipnir/util/symbol_exports.hpp"
11
12namespace slp {
13
14namespace slicing {
15
19struct none_t {};
20
24static inline constexpr none_t _;
25
26} // namespace slicing
27
31class SLEIPNIR_DLLEXPORT Slice {
32 public:
34 int start = 0;
35
37 int stop = 0;
38
40 int step = 1;
41
45 constexpr Slice() = default;
46
50 // NOLINTNEXTLINE (google-explicit-constructor)
52 : Slice(0, std::numeric_limits<int>::max(), 1) {}
53
59 // NOLINTNEXTLINE (google-explicit-constructor)
60 constexpr Slice(int start) {
61 this->start = start;
62 this->stop = (start == -1) ? std::numeric_limits<int>::max() : start + 1;
63 this->step = 1;
64 }
65
72 template <typename Start, typename Stop>
73 requires(std::same_as<Start, slicing::none_t> ||
74 std::convertible_to<Start, int>) &&
75 (std::same_as<Stop, slicing::none_t> ||
76 std::convertible_to<Stop, int>)
77 constexpr Slice(Start start, Stop stop)
78 : Slice(std::move(start), std::move(stop), 1) {}
79
87 template <typename Start, typename Stop, typename Step>
88 requires(std::same_as<Start, slicing::none_t> ||
89 std::convertible_to<Start, int>) &&
90 (std::same_as<Stop, slicing::none_t> ||
91 std::convertible_to<Stop, int>) &&
92 (std::same_as<Step, slicing::none_t> ||
93 std::convertible_to<Step, int>)
94 constexpr Slice(Start start, Stop stop, Step step) {
95 if constexpr (std::same_as<Step, slicing::none_t>) {
96 this->step = 1;
97 } else {
98 slp_assert(step != 0);
99
100 this->step = step;
101 }
102
103 // Avoid UB for step = -step if step is INT_MIN
104 if (this->step == std::numeric_limits<int>::min()) {
105 this->step = -std::numeric_limits<int>::max();
106 }
107
108 if constexpr (std::same_as<Start, slicing::none_t>) {
109 if (this->step < 0) {
110 this->start = std::numeric_limits<int>::max();
111 } else {
112 this->start = 0;
113 }
114 } else {
115 this->start = start;
116 }
117
118 if constexpr (std::same_as<Stop, slicing::none_t>) {
119 if (this->step < 0) {
120 this->stop = std::numeric_limits<int>::min();
121 } else {
122 this->stop = std::numeric_limits<int>::max();
123 }
124 } else {
125 this->stop = stop;
126 }
127 }
128
136 constexpr int adjust(int length) {
137 slp_assert(step != 0);
138 slp_assert(step >= -std::numeric_limits<int>::max());
139
140 if (start < 0) {
141 start += length;
142
143 if (start < 0) {
144 start = (step < 0) ? -1 : 0;
145 }
146 } else if (start >= length) {
147 start = (step < 0) ? length - 1 : length;
148 }
149
150 if (stop < 0) {
151 stop += length;
152
153 if (stop < 0) {
154 stop = (step < 0) ? -1 : 0;
155 }
156 } else if (stop >= length) {
157 stop = (step < 0) ? length - 1 : length;
158 }
159
160 if (step < 0) {
161 if (stop < start) {
162 return (start - stop - 1) / -step + 1;
163 } else {
164 return 0;
165 }
166 } else {
167 if (start < stop) {
168 return (stop - start - 1) / step + 1;
169 } else {
170 return 0;
171 }
172 }
173 }
174};
175
176} // namespace slp
Definition intrusive_shared_ptr.hpp:29
Definition slice.hpp:31
constexpr Slice()=default
constexpr Slice(Start start, Stop stop)
Definition slice.hpp:77
constexpr Slice(slicing::none_t)
Definition slice.hpp:51
constexpr int adjust(int length)
Definition slice.hpp:136
constexpr Slice(Start start, Stop stop, Step step)
Definition slice.hpp:94
constexpr Slice(int start)
Definition slice.hpp:60
Definition slice.hpp:19