Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_disjoint_sparse_table.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
87# ifndef TPL_DISJOINT_SPARSE_TABLE_H
88# define TPL_DISJOINT_SPARSE_TABLE_H
89
90# include <bit>
91# include <cassert>
92# include <cstdlib>
93# include <concepts>
94# include <initializer_list>
95# include <type_traits>
96# include <vector>
97# include <utility>
98# include <algorithm>
99# include <ah-concepts.H>
100# include <tpl_array.H>
101# include <tpl_dynList.H>
102# include <ahFunction.H>
103# include <ah-errors.H>
104
105namespace Aleph
106{
115 template <typename F, typename T>
117
150 template <typename T, class Op>
153 {
154 Array<T> data; // original values: data[i] = a[i]
155 Array<T> table; // flattened 2D: table[k * n + i]
156 size_t n = 0; // number of logical elements
157 size_t levels = 0; // number of levels
158
159 Op op;
160
162 T & at(const size_t k, const size_t i) { return table(k * n + i); }
163 const T & at(const size_t k, const size_t i) const
164 {
165 return table(k * n + i);
166 }
167
173 static constexpr size_t compute_levels(const size_t nn) noexcept
174 {
175 if (nn <= 1) return 0;
176 return static_cast<size_t>(std::bit_width(nn - 1));
177 }
178
185 void build()
186 {
187 if (n <= 1)
188 return;
189
190 for (size_t k = 0; k < levels; ++k)
191 {
192 const size_t half = size_t{1} << k;
193 const size_t block_sz = half << 1;
194
195 for (size_t b = 0; b < n; b += block_sz)
196 {
197 const size_t mid = b + half;
198 if (mid > n) break;
199
200 // Suffix aggregates: from mid-1 going left to b
201 at(k, mid - 1) = data(mid - 1);
202 for (size_t i = mid - 1; i > b; --i)
203 at(k, i - 1) = op(data(i - 1), at(k, i));
204
205 // Prefix aggregates: from mid-going right
206 if (mid < n)
207 {
208 at(k, mid) = data(mid);
209 const size_t right_end = std::min(b + block_sz, n);
210 for (size_t i = mid + 1; i < right_end; ++i)
211 at(k, i) = op(at(k, i - 1), data(i));
212 }
213 }
214 }
215 }
216
218 template <class Getter>
220 {
221 for (size_t i = 0; i < n; ++i)
222 data(i) = getter(i);
223 }
224
226 template <class AlephIt>
228 {
229 size_t i = 0;
230 for (; it.has_curr(); it.next_ne())
231 data(i++) = it.get_curr();
232 }
233
234 public:
236 using Item_Type = T;
237
245 Gen_Disjoint_Sparse_Table(const size_t num, const T & init_val,
246 Op oper = Op())
247 : data(Array<T>::create(std::max(num, size_t{1}))),
248 table(Array<T>::create(
249 std::max(compute_levels(num) * num, size_t{1}))),
250 n(num), levels(compute_levels(num)), op(oper)
251 {
252 fill_data([&init_val](size_t) { return init_val; });
253 build();
254 }
255
264 Gen_Disjoint_Sparse_Table(std::initializer_list<T> il, Op oper = Op())
265 : data(Array<T>::create(std::max(il.size(), size_t{1}))),
266 table(Array<T>::create(
267 std::max(compute_levels(il.size()) * il.size(), size_t{1}))),
269 {
270 auto it = il.begin();
271 fill_data([&it](size_t) { return *it++; });
272 build();
273 }
274
281 : data(Array<T>::create(std::max(values.size(), size_t{1}))),
282 table(Array<T>::create(
284 size_t{1}))),
286 {
287 fill_data([&values](size_t i) { return values(i); });
288 build();
289 }
290
296 Gen_Disjoint_Sparse_Table(const std::vector<T> & values,
297 Op oper = Op())
298 : data(Array<T>::create(std::max(values.size(), size_t{1}))),
299 table(Array<T>::create(
301 size_t{1}))),
303 {
304 fill_data([&values](size_t i) { return values[i]; });
305 build();
306 }
307
314 : data(Array<T>::create(std::max(values.size(), size_t{1}))),
315 table(Array<T>::create(
317 size_t{1}))),
319 {
321 build();
322 }
323
325
327 = default;
328
330 = default;
331
334
347 T query(const size_t l, const size_t r) const
348 {
350 << "Gen_Disjoint_Sparse_Table::query: r=" << r << " >= n=" << n;
352 << "Gen_Disjoint_Sparse_Table::query: l=" << l << " > r=" << r;
353
354 if (l == r)
355 return data(l);
356
357 const size_t k = static_cast<size_t>(std::bit_width(l ^ r)) - 1;
358 return op(at(k, l), at(k, r));
359 }
360
368 T get(const size_t i) const
369 {
371 << "Gen_Disjoint_Sparse_Table::get: index " << i
372 << " >= size " << n;
373
374 return data(i);
375 }
376
378 [[nodiscard]] constexpr size_t size() const noexcept { return n; }
379
381 [[nodiscard]] constexpr bool is_empty() const noexcept { return n == 0; }
382
384 [[nodiscard]] constexpr size_t num_levels() const noexcept
385 {
386 return levels;
387 }
388
394 {
395 auto ret = Array<T>::create(n);
396 for (size_t i = 0; i < n; ++i)
397 ret(i) = data(i);
398 return ret;
399 }
400
403 {
404 data.swap(other.data);
405 table.swap(other.table);
406 std::swap(n, other.n);
407 std::swap(levels, other.levels);
408 std::swap(op, other.op);
409 }
410 };
411
412
430 template <typename T>
432 : public Gen_Disjoint_Sparse_Table<T, Aleph::plus<T>>
433 {
435 using Base::Base; // inherit all constructors
436 };
437
455 template <typename T>
457 : public Gen_Disjoint_Sparse_Table<T, Aleph::multiplies<T>>
458 {
460 using Base::Base; // inherit all constructors
461 };
462
463} // end namespace Aleph
464
465# endif /* TPL_DISJOINT_SPARSE_TABLE_H */
C++20 concepts hub: comparison, BST policy, and Aleph container concepts.
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:584
Standard functor implementations and comparison objects.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:196
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
Disjoint Sparse Table over an arbitrary associative binary operation.
Gen_Disjoint_Sparse_Table(const size_t num, const T &init_val, Op oper=Op())
Construct a disjoint sparse table with num elements, all equal to init_val.
void swap(Gen_Disjoint_Sparse_Table &other) noexcept
Swap this table with other in O(1).
constexpr bool is_empty() const noexcept
True if the table contains no elements.
void fill_data_from_aleph_it(AlephIt it)
Fill data array from an Aleph-style iterator.
Gen_Disjoint_Sparse_Table(const DynList< T > &values, Op oper=Op())
Construct from a DynList<T> in O(n log n) time.
T & at(const size_t k, const size_t i)
Access table[k][i] (0-based row k, 0-based column i).
Array< T > values() const
Reconstruct all original values into an Array.
const T & at(const size_t k, const size_t i) const
T get(const size_t i) const
Retrieve the value a[i] in O(1).
constexpr size_t num_levels() const noexcept
Number of precomputed levels.
T query(const size_t l, const size_t r) const
Range query over [l, r] in O(1).
Gen_Disjoint_Sparse_Table(const Array< T > &values, Op oper=Op())
Construct from an Array<T> in O(n log n) time.
void fill_data(Getter getter)
Fill data array from a 0-based indexed getter.
Gen_Disjoint_Sparse_Table(std::initializer_list< T > il, Op oper=Op())
Construct from an initializer list in O(n log n) time.
Gen_Disjoint_Sparse_Table(const std::vector< T > &values, Op oper=Op())
Construct from a std::vector<T> in O(n log n) time.
void build()
Build the disjoint sparse table from the data array.
constexpr size_t size() const noexcept
Number of logical elements.
Gen_Disjoint_Sparse_Table(const Gen_Disjoint_Sparse_Table &)=default
Gen_Disjoint_Sparse_Table(Gen_Disjoint_Sparse_Table &&) noexcept=default
T Item_Type
The type of the element stored in the table.
static constexpr size_t compute_levels(const size_t nn) noexcept
Compute the number of levels for n elements.
A binary functor closed over T.
Binary operation compatible with Disjoint Sparse Table queries.
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4121
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
STL namespace.
Disjoint Sparse Table for range product queries.
Disjoint Sparse Table for range sum queries.
static int * k
gsl_rng * r
Dynamic array container with automatic resizing.
Alias for htlist.H (DynList implementation).
DynList< int > l