Skip to content

Commit dc240bc

Browse files
committed
Remove step as bit_array_ref cannot accomodate
1 parent dea8b06 commit dc240bc

4 files changed

Lines changed: 140 additions & 61 deletions

File tree

CMakePresets.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,17 @@
340340
"rhs": "Linux"
341341
}
342342
},
343+
{
344+
"name": "tests_linux_clang_libstdcxx",
345+
"configurePreset": "tests_linux_clang_libstdcxx",
346+
"targets": "bitlib-tests",
347+
"jobs": 0,
348+
"condition": {
349+
"type": "equals",
350+
"lhs": "${hostSystemName}",
351+
"rhs": "Linux"
352+
}
353+
},
343354
{
344355
"name": "coverage_linux_clang_libcxx",
345356
"configurePreset": "coverage_linux_clang_libcxx",
@@ -443,6 +454,15 @@
443454
"rhs": "Linux"
444455
}
445456
},
457+
{
458+
"name": "tests_linux_clang_libstdcxx",
459+
"configurePreset": "tests_linux_clang_libstdcxx",
460+
"condition": {
461+
"type": "equals",
462+
"lhs": "${hostSystemName}",
463+
"rhs": "Linux"
464+
}
465+
},
446466
{
447467
"name": "coverage_linux_clang_libcxx",
448468
"configurePreset": "coverage_linux_clang_libcxx",

include/bitlib/bit-containers/bit_array_base.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ class bit_array_base {
155155

156156
template <std::integral U = int>
157157
constexpr auto operator()(const bounds<U>& slice) const noexcept {
158-
return bit_array_ref<bit_value, const word_type>(&this->at(slice.begin), slice.size());
158+
auto bounds_resolved = slice.resolve(derived().size());
159+
assert(bounds_resolved.first <= bounds_resolved.second);
160+
auto bounds_size = bounds_resolved.second - bounds_resolved.first;
161+
return bit_array_ref<bit_value, const word_type>(&this->at(bounds_resolved.first), bounds_size);
159162
}
160163

161164
/**
@@ -167,7 +170,10 @@ class bit_array_base {
167170

168171
template <std::integral U = int>
169172
constexpr auto operator()(const bounds<U>& slice) noexcept {
170-
return bit_array_ref<bit_value, word_type>(&this->at(slice.begin), slice.size());
173+
auto bounds_resolved = slice.resolve(derived().size());
174+
assert(bounds_resolved.first <= bounds_resolved.second);
175+
auto bounds_size = bounds_resolved.second - bounds_resolved.first;
176+
return bit_array_ref<bit_value, word_type>(&this->at(bounds_resolved.first), bounds_size);
171177
}
172178

173179
// Common operations

include/bitlib/bit-containers/bounds.hpp

Lines changed: 107 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -18,78 +18,129 @@ namespace bit {
1818
template <typename Derived, typename T, typename W, typename It, typename CIt>
1919
class bit_array_base;
2020

21-
template <std::integral size_type = uint32_t>
21+
template <std::signed_integral size_type = int>
2222
class bounds {
2323
template <typename Derived, typename T, typename W, typename It, typename CIt>
2424
friend class bit_array_base;
25-
private:
26-
size_type begin;
27-
size_type end;
28-
size_type step;
29-
30-
public:
31-
using None = std::tuple<>;
32-
constexpr bounds() = delete;
33-
constexpr bounds(const bounds& other) = default;
34-
constexpr bounds(const bounds&& other)
35-
: begin(other.begin), end(other.end), step(other.step) {
25+
26+
public:
27+
using None_t = std::tuple<>;
28+
static constexpr None_t None = None_t{};
29+
30+
private:
31+
using var_t = std::variant<None_t, size_type>;
32+
var_t begin;
33+
var_t end;
34+
35+
public:
36+
constexpr bounds() : begin(None), end(None) {
37+
}
38+
constexpr bounds(const bounds& other) = default;
39+
constexpr bounds(const bounds&& other)
40+
: begin(other.begin), end(other.end) {
41+
}
42+
constexpr bounds(const size_type pos)
43+
: begin(pos), end(None) {
44+
}
45+
constexpr bounds(const size_type begin, const size_type end)
46+
: begin(begin), end(end) {
47+
}
48+
constexpr bounds(std::initializer_list<var_t> components) {
49+
if (components.size() > 3) {
50+
throw std::invalid_argument("Initializer list must have at most 2 elements");
3651
}
37-
constexpr bounds(const size_type& pos)
38-
: begin(pos), end(pos + 1), step(1) {
52+
auto it = components.begin();
53+
begin = None;
54+
end = None;
55+
if (components.size() >= 1) {
56+
begin = *it;
3957
}
40-
constexpr bounds(const size_type& begin, const size_type& end, const size_type& step = 1)
41-
: begin(begin), end(end), step(step) {
58+
if (components.size() >= 2) {
59+
it++;
60+
end = *it;
4261
}
43-
constexpr bounds(const None begin, const size_type& end, const size_type& step = 1)
44-
: begin(0), end(end), step(step) {
62+
if (std::holds_alternative<size_type>(begin)) {
63+
std::cout << "pos " << std::get<size_type>(begin) << ", ";
64+
} else {
65+
std::cout << "None, ";
4566
}
46-
constexpr bounds(std::initializer_list<std::variant<None, size_type>> components) {
47-
if (components.size() > 3) {
48-
throw std::invalid_argument("Initializer list must have at most 2 elements");
49-
}
50-
auto it = components.begin();
51-
begin = 0;
52-
end = 1;
53-
step = 1;
54-
if (components.size() >= 1) {
55-
if (std::holds_alternative<size_type>(*it)) {
56-
begin = std::get<size_type>(*it);
57-
end = begin + 1;
58-
} else {
59-
std::cout << "None for [0]" << std::endl;
60-
begin = 0;
61-
end = 1;
62-
}
63-
}
64-
if (components.size() >= 2) {
65-
it++;
66-
if (std::holds_alternative<size_type>(*it)) {
67-
end = std::get<size_type>(*it);
68-
}
69-
}
70-
if (components.size() >= 3) {
71-
it++;
72-
if (std::holds_alternative<size_type>(*it)) {
73-
step = std::get<size_type>(*it);
74-
} else {
75-
step = 1;
76-
}
77-
}
67+
if (std::holds_alternative<size_type>(end)) {
68+
std::cout << "pos" << std::get<size_type>(end) << std::endl;
69+
} else {
70+
std::cout << "None" << std::endl;
7871
}
72+
}
7973

8074
constexpr bool operator==(const bounds& other) const = default;
8175
constexpr auto operator<=>(const bounds& other) const = default;
8276

83-
constexpr bounds& operator+=(const size_type& size) {
84-
end = begin + size;
77+
constexpr bounds& operator+=(const size_t& _size) {
78+
const size_type size = static_cast<size_type>(_size);
79+
if (std::holds_alternative<size_type>(end)) {
80+
size_type end_pos = std::get<size_type>(end);
81+
if (end_pos >= 0) {
82+
end = end_pos + size;
83+
} else {
84+
end = ((size_type(-1) - size) < end_pos) ? size_type(-1) : (end_pos + size);
85+
}
86+
} else if (std::holds_alternative<size_type>(begin)) {
87+
end = std::get<size_type>(begin) + size;
88+
}
8589
return *this;
8690
}
87-
constexpr bounds& operator-=(const size_type& size) {
88-
begin = end - size;
91+
92+
constexpr bounds& operator-=(const size_t& _size) {
93+
const size_type size = static_cast<size_type>(_size);
94+
if (std::holds_alternative<size_type>(begin)) {
95+
size_type begin_pos = std::get<size_type>(begin);
96+
if (!std::holds_alternative<size_type>(end)) {
97+
end = begin_pos + 1;
98+
begin = begin_pos + 1 - size;
99+
} else {
100+
if (begin_pos < 0) {
101+
begin = begin_pos - size;
102+
} else {
103+
begin = ((size_type(0) + size) > begin_pos) ? size_type(0) : (begin_pos - size);
104+
}
105+
}
106+
}
89107
return *this;
90108
}
91-
constexpr size_type size() const {
92-
return end - begin;
109+
110+
constexpr std::pair<size_type, size_type> resolve(size_t _length) const {
111+
const size_type length = static_cast<size_type>(_length);
112+
// Helper: translate a possibly-negative int into a signed index
113+
auto translate_index = [&](size_type idx) -> size_type {
114+
size_type x = (idx);
115+
if (x < size_type(0)) {
116+
x += length;
117+
}
118+
return x;
119+
};
120+
121+
// 1) Compute raw_start
122+
size_type raw_start;
123+
if (std::holds_alternative<None_t>(begin)) {
124+
raw_start = size_type(0);
125+
} else {
126+
raw_start = translate_index(std::get<size_type>(begin));
127+
}
128+
129+
// 2) Compute raw_end
130+
size_type raw_end;
131+
if (std::holds_alternative<None_t>(end)) {
132+
raw_end = length;
133+
} else {
134+
raw_end = translate_index(std::get<size_type>(end));
135+
}
136+
137+
// 3) Clamp into [0..L]
138+
return {std::clamp(raw_start,
139+
size_type(0),
140+
length),
141+
std::clamp(raw_end,
142+
size_type(0),
143+
length)};
93144
}
94145
};
95146

test/src/test-array.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,12 @@ TEST(BitArrayTest, SliceWithClass) {
510510
EXPECT_EQ(span3, span2);
511511
auto span4 = arr(bit::bounds{7} -= 4);
512512
EXPECT_EQ(span4, span2);
513-
bit::bounds bounds({}, 5);
514-
EXPECT_EQ(bounds.size(), 5);
513+
auto span5 = arr({4, {}});
514+
auto span6 = arr(4, 32);
515+
EXPECT_EQ(span5, span6);
516+
bit::bounds bounds(0, 5);
515517
bit::bounds bounds2{{}, 5};
516-
EXPECT_EQ(bounds, bounds2);
518+
EXPECT_EQ(bounds.resolve(32), bounds2.resolve(32));
517519
}
518520

519521
TEST(BitArrayTest, SliceModify) {

0 commit comments

Comments
 (0)