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 <tpl_array.H>
100# include <tpl_dynList.H>
101# include <ahFunction.H>
102# include <ah-errors.H>
103
104namespace Aleph
105{
115 template <typename F, typename T>
117 requires(const F& f, const T& a, const T& b)
118 {
119 { f(a, b) } -> std::convertible_to<T>;
120 };
121
154 template <typename T, class Op>
157 {
158 Array<T> data; // original values: data[i] = a[i]
159 Array<T> table; // flattened 2D: table[k * n + i]
160 size_t n = 0; // number of logical elements
161 size_t levels = 0; // number of levels
162
164
166 T & at(const size_t k, const size_t i) { return table(k * n + i); }
167 const T & at(const size_t k, const size_t i) const
168 {
169 return table(k * n + i);
170 }
171
177 static constexpr size_t compute_levels(const size_t nn) noexcept
178 {
179 if (nn <= 1) return 0;
180 return static_cast<size_t>(std::bit_width(nn - 1));
181 }
182
189 void build()
190 {
191 if (n <= 1)
192 return;
193
194 for (size_t k = 0; k < levels; ++k)
195 {
196 const size_t half = size_t{1} << k;
197 const size_t block_sz = half << 1;
198
199 for (size_t b = 0; b < n; b += block_sz)
200 {
201 const size_t mid = b + half;
202 if (mid > n) break;
203
204 // Suffix aggregates: from mid-1 going left to b
205 at(k, mid - 1) = data(mid - 1);
206 for (size_t i = mid - 1; i > b; --i)
207 at(k, i - 1) = op(data(i - 1), at(k, i));
208
209 // Prefix aggregates: from mid-going right
210 if (mid < n)
211 {
212 at(k, mid) = data(mid);
213 const size_t right_end = std::min(b + block_sz, n);
214 for (size_t i = mid + 1; i < right_end; ++i)
215 at(k, i) = op(at(k, i - 1), data(i));
216 }
217 }
218 }
219 }
220
222 template <class Getter>
224 {
225 for (size_t i = 0; i < n; ++i)
226 data(i) = getter(i);
227 }
228
230 template <class AlephIt>
232 {
233 size_t i = 0;
234 for (; it.has_curr(); it.next_ne())
235 data(i++) = it.get_curr();
236 }
237
238 public:
240 using Item_Type = T;
241
249 Gen_Disjoint_Sparse_Table(const size_t num, const T & init_val,
250 Op oper = Op())
251 : data(Array<T>::create(std::max(num, size_t{1}))),
252 table(Array<T>::create(
253 std::max(compute_levels(num) * num, size_t{1}))),
254 n(num), levels(compute_levels(num)), op(oper)
255 {
256 fill_data([&init_val](size_t) { return init_val; });
257 build();
258 }
259
268 Gen_Disjoint_Sparse_Table(std::initializer_list<T> il, Op oper = Op())
269 : data(Array<T>::create(std::max(il.size(), size_t{1}))),
270 table(Array<T>::create(
271 std::max(compute_levels(il.size()) * il.size(), size_t{1}))),
273 {
274 auto it = il.begin();
275 fill_data([&it](size_t) { return *it++; });
276 build();
277 }
278
285 : data(Array<T>::create(std::max(values.size(), size_t{1}))),
286 table(Array<T>::create(
288 size_t{1}))),
290 {
291 fill_data([&values](size_t i) { return values(i); });
292 build();
293 }
294
300 Gen_Disjoint_Sparse_Table(const std::vector<T> & values,
301 Op oper = Op())
302 : data(Array<T>::create(std::max(values.size(), size_t{1}))),
303 table(Array<T>::create(
305 size_t{1}))),
307 {
308 fill_data([&values](size_t i) { return values[i]; });
309 build();
310 }
311
318 : data(Array<T>::create(std::max(values.size(), size_t{1}))),
319 table(Array<T>::create(
321 size_t{1}))),
323 {
325 build();
326 }
327
329
331 = default;
332
334 = default;
335
338
351 T query(const size_t l, const size_t r) const
352 {
354 << "Gen_Disjoint_Sparse_Table::query: r=" << r << " >= n=" << n;
356 << "Gen_Disjoint_Sparse_Table::query: l=" << l << " > r=" << r;
357
358 if (l == r)
359 return data(l);
360
361 const size_t k = static_cast<size_t>(std::bit_width(l ^ r)) - 1;
362 return op(at(k, l), at(k, r));
363 }
364
372 T get(const size_t i) const
373 {
375 << "Gen_Disjoint_Sparse_Table::get: index " << i
376 << " >= size " << n;
377
378 return data(i);
379 }
380
382 [[nodiscard]] constexpr size_t size() const noexcept { return n; }
383
385 [[nodiscard]] constexpr bool is_empty() const noexcept { return n == 0; }
386
388 [[nodiscard]] constexpr size_t num_levels() const noexcept
389 {
390 return levels;
391 }
392
398 {
399 auto ret = Array<T>::create(n);
400 for (size_t i = 0; i < n; ++i)
401 ret(i) = data(i);
402 return ret;
403 }
404
407 {
408 data.swap(other.data);
409 table.swap(other.table);
410 std::swap(n, other.n);
411 std::swap(levels, other.levels);
412 std::swap(op, other.op);
413 }
414 };
415
416
434 template <typename T>
436 : public Gen_Disjoint_Sparse_Table<T, Aleph::plus<T>>
437 {
439 using Base::Base; // inherit all constructors
440 };
441
459 template <typename T>
461 : public Gen_Disjoint_Sparse_Table<T, Aleph::multiplies<T>>
462 {
464 using Base::Base; // inherit all constructors
465 };
466
467} // end namespace Aleph
468
469# endif /* TPL_DISJOINT_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
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
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.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
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:4110
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.
Disjoint Sparse Table for range product queries.
Disjoint Sparse Table for range sum queries.
Dynamic array container with automatic resizing.
Alias for htlist.H (DynList implementation).
DynList< int > l