Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_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
69# ifndef TPL_SPARSE_TABLE_H
70# define TPL_SPARSE_TABLE_H
71
72# include <bit>
73# include <cassert>
74# include <cstdlib>
75# include <concepts>
76# include <initializer_list>
77# include <type_traits>
78# include <vector>
79# include <utility>
80# include <algorithm>
81# include <tpl_array.H>
82# include <tpl_dynList.H>
83# include <ahFunction.H>
84# include <ah-errors.H>
85
86namespace Aleph
87{
97 template <typename F, typename T>
98 concept SparseTableOp =
99 requires(const F& f, const T& a, const T& b)
100 {
101 { f(a, b) } -> std::convertible_to<T>;
102 };
103
111 template <std::totally_ordered T>
112 struct Min_Op
113 {
114 constexpr T operator()(const T & a, const T & b) const noexcept
115 {
116 return a <= b ? a : b;
117 }
118 };
119
127 template <std::totally_ordered T>
128 struct Max_Op
129 {
130 constexpr T operator()(const T & a, const T & b) const noexcept
131 {
132 return a >= b ? a : b;
133 }
134 };
135
166 template <typename T, class Op>
167 requires SparseTableOp<Op, T>
169 {
170 Array<T> table; // flattened 2D: table[k * n + i]
171 Array<size_t> log_tbl; // log_tbl[len] = floor(log2(len)) for len in [1..n]
172 size_t n = 0; // number of logical elements
173 size_t levels = 0; // number of levels = floor(log2(n)) + 1
174
176
178 T & at(const size_t k, const size_t i) { return table(k * n + i); }
179 const T & at(const size_t k, const size_t i) const { return table(k * n + i); }
180
182 static constexpr size_t compute_levels(const size_t nn) noexcept
183 {
184 return nn == 0 ? 0 : static_cast<size_t>(std::bit_width(nn));
185 }
186
188 static constexpr size_t compute_cells(const size_t nn) noexcept
189 {
190 return nn == 0 ? 1 : compute_levels(nn) * nn;
191 }
192
195 {
196 if (n == 0)
197 return;
198
200 log_tbl(0) = 0;
201 log_tbl(1) = 0;
202 for (size_t i = 2; i <= n; ++i)
203 log_tbl(i) = log_tbl(i / 2) + 1;
204 }
205
208 {
209 // table[k][i] = Op(table[k-1][i], table[k-1][i + 2^(k-1)])
210 for (size_t k = 1; k < levels; ++k)
211 {
212 const size_t half = size_t{1} << (k - 1);
213 const size_t limit = n - (size_t{1} << k) + 1;
214 for (size_t i = 0; i < limit; ++i)
215 at(k, i) = op(at(k - 1, i), at(k - 1, i + half));
216 }
217 }
218
220 template <class Getter>
222 {
223 // Level 0: intervals of length 1
224 for (size_t i = 0; i < n; ++i)
225 at(0, i) = getter(i);
226
228 }
229
231 template <class AlephIt>
233 {
234 size_t i = 0;
235 for (; it.has_curr(); it.next_ne())
236 at(0, i++) = it.get_curr();
237
239 }
240
241 public:
243 using Item_Type = T;
244
252 Gen_Sparse_Table(const size_t num, const T & init_val,
253 Op oper = Op())
254 : table(Array<T>::create(compute_cells(num))),
255 n(num), levels(compute_levels(num)), op(oper)
256 {
258 if (n > 0)
259 fill_and_build([&init_val](size_t) { return init_val; });
260 }
261
270 Gen_Sparse_Table(std::initializer_list<T> il, Op oper = Op())
271 : table(Array<T>::create(compute_cells(il.size()))),
273 {
275 if (n > 0)
276 {
277 auto it = il.begin();
278 fill_and_build([&it](size_t) { return *it++; });
279 }
280 }
281
288 : table(Array<T>::create(compute_cells(values.size()))),
290 {
292 if (n > 0)
293 fill_and_build([&values](size_t i) { return values(i); });
294 }
295
301 Gen_Sparse_Table(const std::vector<T> & values, Op oper = Op())
302 : table(Array<T>::create(compute_cells(values.size()))),
304 {
306 if (n > 0)
307 fill_and_build([&values](size_t i) { return values[i]; });
308 }
309
316 : table(Array<T>::create(compute_cells(values.size()))),
318 {
320 if (n > 0)
321 fill_from_aleph_it(values.get_it());
322 }
323
325
329
331
335
347 T query(const size_t l, const size_t r) const
348 {
350 << "Gen_Sparse_Table::query: r=" << r << " >= n=" << n;
352 << "Gen_Sparse_Table::query: l=" << l << " > r=" << r;
353
354 const size_t k = log_tbl(r - l + 1);
355 return op(at(k, l), at(k, r - (size_t{1} << k) + 1));
356 }
357
365 T get(const size_t i) const
366 {
368 << "Gen_Sparse_Table::get: index " << i << " >= size " << n;
369
370 return at(0, i);
371 }
372
374 [[nodiscard]] constexpr size_t size() const noexcept { return n; }
375
377 [[nodiscard]] constexpr bool is_empty() const noexcept { return n == 0; }
378
380 [[nodiscard]] constexpr size_t num_levels() const noexcept
381 {
382 return levels;
383 }
384
390 {
391 auto ret = Array<T>::create(n);
392 for (size_t i = 0; i < n; ++i)
393 ret(i) = at(0, i);
394 return ret;
395 }
396
398 void swap(Gen_Sparse_Table & other) noexcept
399 {
400 table.swap(other.table);
401 log_tbl.swap(other.log_tbl);
402 std::swap(n, other.n);
403 std::swap(levels, other.levels);
404 std::swap(op, other.op);
405 }
406 };
407
408
426 template <std::totally_ordered T>
428 : public Gen_Sparse_Table<T, Min_Op<T>>
429 {
431 using Base::Base; // inherit all constructors
432 };
433
451 template <std::totally_ordered T>
453 : public Gen_Sparse_Table<T, Max_Op<T>>
454 {
456 using Base::Base; // inherit all constructors
457 };
458
459} // end namespace Aleph
460
461# endif /* TPL_SPARSE_TABLE_H */
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:579
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:191
void swap(Array &s) noexcept
Swap this with s
Definition tpl_array.H:221
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
Sparse Table over an arbitrary associative and idempotent binary operation.
void build_upper_levels()
Build levels k >= 1 from already-populated level 0.
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 (floor(log2(n)) + 1).
Array< T > values() const
Reconstruct all original values into an Array.
void fill_and_build(Getter getter)
Fill level 0 from a 0-based indexed getter and build higher levels.
constexpr size_t size() const noexcept
Number of logical elements.
Gen_Sparse_Table(std::initializer_list< T > il, Op oper=Op())
Construct from an initializer list in O(n log n) time.
Gen_Sparse_Table(const std::vector< T > &values, Op oper=Op())
Construct from a std::vector<T> in O(n log n) time.
static constexpr size_t compute_cells(const size_t nn) noexcept
Number of flattened cells needed to store all levels.
T & at(const size_t k, const size_t i)
Access table[k][i] (0-based row k, 0-based column i).
void fill_from_aleph_it(AlephIt it)
Fill level 0 from an Aleph-style iterator and build higher levels.
Gen_Sparse_Table(const size_t num, const T &init_val, Op oper=Op())
Construct a sparse table with num elements, all equal to init_val.
Gen_Sparse_Table(const Gen_Sparse_Table &)=default
const T & at(const size_t k, const size_t i) const
static constexpr size_t compute_levels(const size_t nn) noexcept
Compute levels = floor(log2(n)) + 1; 0 if n == 0.
constexpr bool is_empty() const noexcept
True if the table contains no elements.
Gen_Sparse_Table(const DynList< T > &values, Op oper=Op())
Construct from a DynList<T> in O(n log n) time.
T query(const size_t l, const size_t r) const
Range query over [l, r] in O(1).
T Item_Type
The type of the element stored in the table.
void swap(Gen_Sparse_Table &other) noexcept
Swap this table with other in O(1).
Gen_Sparse_Table(Gen_Sparse_Table &&) noexcept(std::is_nothrow_move_constructible_v< Array< T > > &&std::is_nothrow_move_constructible_v< Op >)=default
void build_log_table()
Precompute the log lookup table for lengths [0..n].
Gen_Sparse_Table(const Array< T > &values, Op oper=Op())
Construct from an Array<T> in O(n log n) time.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
Binary operation compatible with Sparse Table queries.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Functor returning the maximum of two values.
constexpr T operator()(const T &a, const T &b) const noexcept
Sparse Table for range maximum queries.
Functor returning the minimum of two values.
constexpr T operator()(const T &a, const T &b) const noexcept
Sparse Table for range minimum queries.
Dynamic array container with automatic resizing.
Alias for htlist.H (DynList implementation).
DynList< int > l