entttree 0.1.0
Hierarchical entity management for EnTT
Loading...
Searching...
No Matches
position.cpp
1#include <algorithm>
2#include <compare>
3
4#include <entttree/position.h>
5
6namespace entttree {
7
9
10Position::symbol_t* Position::_data() {
11 return _size > K ? _symbol_ptr : _symbols;
12}
13
14const Position::symbol_t* Position::_data() const {
15 return _size > K ? _symbol_ptr : _symbols;
16}
17
18Position::symbol_t Position::operator[](size_t i) const {
19 if (i >= _size) return 0;
20 return _data()[i];
21}
22
23void Position::_push_back(symbol_t s) {
24 if (_size < K) [[likely]] {
25 _symbols[_size] = s;
26 } else {
27 symbol_t* cur_data = _data();
28 symbol_t* new_ptr = new symbol_t[_size + 1];
29 std::copy(cur_data, cur_data + _size, new_ptr);
30 new_ptr[_size] = s;
31 if (_size > K) delete[] _symbol_ptr;
32 _symbol_ptr = new_ptr;
33 }
34 ++_size;
35}
36
37
39
40Position::Position(size_t n):
41 _symbols{},
42 _size(n)
43{
44 if (n > K) {
45 _symbol_ptr = new symbol_t[n];
46 }
47}
48
49Position::Position():Position(2) {
50 _data()[1] = HIGH_BIT;
51}
52
54 _size(other._size)
55{
56 symbol_t* data;
57 if (_size > K) {
58 _symbol_ptr = new symbol_t[_size];
60 } else {
61 data = _symbols;
62 }
63 const symbol_t* other_data = other._data();
64 std::copy(other_data, other_data + _size, data);
65}
66
67Position::Position(Position&& other):
68 _size(other._size)
69{
70 if (_size > K) {
72 other._size = 0;
73 } else {
74 const symbol_t* other_data = other._data();
75 std::copy(other_data, other_data + _size, _symbols);
76 }
77}
78
79Position::~Position() {
80 if (_size > K) {
81 delete[] _symbol_ptr;
82 }
83}
84
85
87
88Position& Position::operator=(const Position& other) {
89 if (this == &other) return *this;
90 if (_size > K) {
91 delete[] _symbol_ptr;
92 }
93 _size = other._size;
94 const symbol_t* other_data = other._data();
95 symbol_t* data = _symbols;
96 if (_size > K) {
97 _symbol_ptr = new symbol_t[_size];
98 data = _symbol_ptr;
99 }
100 std::copy(other_data, other_data + _size, data);
101 return *this;
102}
103
104Position& Position::operator=(Position&& other) {
105 if (this == &other) return *this;
106 if (_size > K) {
107 delete[] _symbol_ptr;
108 }
109 _size = other._size;
110 if (_size > K) {
111 _symbol_ptr = other._symbol_ptr;
112 other._size = 0;
113 } else {
114 const symbol_t* other_data = other._symbols;
115 std::copy(other_data, other_data + _size, _symbols);
116 }
117 return *this;
118}
119
120
122
123std::strong_ordering Position::operator<=>(const Position& other) const {
124 size_t n = std::min(_size, other._size);
125 const symbol_t* data_a = _data();
126 const symbol_t* data_b = other._data();
127 for (size_t i = 0; i < n; ++i) {
128 if (data_a[i] < data_b[i]) {
129 return std::strong_ordering::less;
130 } else if (data_a[i] > data_b[i]) {
131 return std::strong_ordering::greater;
132 }
133 }
134 return _size <=> other._size;
135}
136
137
139
141 Position result {_size};
142 uint8_t carry = 1;
143 bool all_zero = true;
144 symbol_t* result_data = result._data();
145 const symbol_t* data = _data();
146 for (int i = int(_size) - 1; i >= 0; --i) {
147 result_data[i] = data[i] + carry;
148 carry = result_data[i] < data[i];
150 }
151 if (all_zero) [[unlikely]] {
152 for (size_t i = 0; i < _size; ++i) {
153 result_data[i] = FULL_SYMBOL;
154 }
155 result._push_back(HIGH_BIT);
156 }
157 return result;
158}
159
161 Position result {_size};
162 symbol_t* result_data = result._data();
163 const symbol_t* data = _data();
164
165 uint8_t borrow = 1;
166 bool all_zero = true;
167 for (int i = int(_size) - 1; i >= 0; --i) {
168 result_data[i] = data[i] - borrow;
169 borrow = result_data[i] > data[i];
171 }
172 if (all_zero) [[unlikely]] {
173 result._push_back(HIGH_BIT);
174 }
175 return result;
176}
177
179 const symbol_t* data_a = _data();
180 const symbol_t* data_b = other._data();
181 size_t sz_a = _size;
182 size_t sz_b = other._size;
183 size_t sz_x = std::max(sz_a, sz_b);
184
185 symbol_t last_a = (sz_x <= sz_a) ? data_a[sz_x - 1] : 0;
186 symbol_t last_b = (sz_x <= sz_b) ? data_b[sz_x - 1] : 0;
187 static_assert(std::is_unsigned_v<symbol_t>, "assumption: symbol_t nonnegative");
188 if (last_a - last_b <= 1 or last_b - last_a <= 1) ++sz_x;
189
191 symbol_t* result_data = result._data();
192 symbol_t carry = 0;
193 for (int i = int(result._size) - 1; i >= 0; --i) {
194 symbol_t a = (i < (int) sz_a ? data_a[i] : 0) >> 1;
195 symbol_t b = (i < (int) sz_b ? data_b[i] : 0) >> 1;
196 if (i > 0) {
197 if (i <= (int) sz_a) a |= (data_a[i - 1] & 1) << (SYMBOL_BITS - 1);
198 if (i <= (int) sz_b) b |= (data_b[i - 1] & 1) << (SYMBOL_BITS - 1);
199 }
200 uint16_t wide = (uint16_t)a + b + carry;
201 result_data[i] = (symbol_t)wide;
202 carry = wide >> SYMBOL_BITS;
203 }
204
205 return result;
206}
207
208Position Position::from_bytes(const symbol_t* data, size_t count) {
209 if (count == 0) return Position(); // fallback to midpoint
210 Position result(count);
211 std::copy(data, data + count, result._data());
212 return result;
213}
214
215} // namespace entttree
216
217
218size_t std::hash<entttree::Position>::operator()(const entttree::Position& pos) const {
219 return geom::hash<entttree::Position,size_t>(pos);
220}
Fractional-index type for ordering siblings in a hierarchy.
A system for maintaining parent-child relationships on entities.
Definition hierarchy.h:37
A fractional index with strong ordering, used for sibling positioning.
Definition position.h:27
symbol_t _symbols[K]
Inline storage for small positions.
Definition position.h:45
static Position from_bytes(const symbol_t *data, size_t count)
Construct a Position from raw symbol bytes.
Definition position.cpp:208
symbol_t * _symbol_ptr
Heap pointer when size exceeds K.
Definition position.h:46
Position()
Construct a Position at the midpoint (0.5).
Definition position.cpp:49
Position after() const
Return a position immediately after this one.
Definition position.cpp:140
Position before() const
Return a position immediately before this one.
Definition position.cpp:160
std::strong_ordering operator<=>(const Position &other) const
Lexicographic three-way comparison.
Definition position.cpp:123
Position between(const Position &other) const
Return a position midway between this position and other.
Definition position.cpp:178
and
Transform a traversal inductively, threading parent context through successors.
Definition traverse.h:542