Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_sparse_table_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
37# include <gtest/gtest.h>
38
39# include <tpl_sparse_table.H>
40
41# include <algorithm>
42# include <cstddef>
43# include <numeric>
44# include <utility>
45# include <vector>
46
47using namespace Aleph;
48using namespace testing;
49
50namespace
51{
52 struct Gcd_Op
53 {
54 int operator()(const int a, const int b) const noexcept
55 {
56 return std::gcd(a, b);
57 }
58 };
59
60 template <typename T, class Op>
61 T fold_range(const std::vector<T> & values,
62 const size_t l, const size_t r, Op op)
63 {
64 T acc = values[l];
65 for (size_t i = l + 1; i <= r; ++i)
66 acc = op(acc, values[i]);
67 return acc;
68 }
69
70 // A bit set whose `+` is union: idempotent, so it must stay accepted.
71 struct Bits
72 {
73 unsigned mask = 0;
74 Bits operator+(const Bits & o) const noexcept { return {mask | o.mask}; }
75 bool operator==(const Bits &) const = default;
76 };
77
78 struct My_Sum
79 {
80 int operator()(const int a, const int b) const noexcept { return a + b; }
81 };
82
83 template <class T, class Op>
84 concept buildable = requires { typename Gen_Sparse_Table<T, Op>; };
85} // namespace
86
87// Opt-in through the customization point.
88template <>
89inline constexpr bool Aleph::is_known_non_idempotent_op<My_Sum, int> = true;
90
91// Known non-idempotent functors are rejected at compile time: a sum table
92// used to compile and answer query(0, 4) over {1..5} with 24 instead of 15.
97static_assert(not SparseTableOp<std::plus<int>, int>);
98
99// Everything else passes, as before.
103constexpr auto min_lambda = [](const int a, const int b) { return std::min(a, b); };
104static_assert(IdempotentOp<decltype(min_lambda), int>);
105
107{
108 Sparse_Table<int> st(std::vector<int>{});
109
110 EXPECT_TRUE(st.is_empty());
111 EXPECT_EQ(st.size(), 0U);
112 EXPECT_EQ(st.num_levels(), 0U);
113
114 EXPECT_THROW(st.get(0), std::out_of_range);
115 EXPECT_THROW(st.query(0, 0), std::out_of_range);
116}
117
119{
121
122 EXPECT_EQ(st.size(), 16U);
124 EXPECT_EQ(st.query(0, 15), 7);
125 EXPECT_EQ(st.query(5, 11), 7);
126
127 for (size_t i = 0; i < st.size(); ++i)
128 EXPECT_EQ(st.get(i), 7);
129}
130
132{
133 const std::vector<int> values = {9, 4, 7, 1, 8, 2, 6, 3, 5, 0};
134 Sparse_Table<int> mn(values);
136
137 for (size_t l = 0; l < values.size(); ++l)
138 for (size_t r = l; r < values.size(); ++r)
139 {
140 const int expected_min = *std::min_element(values.begin() + l,
141 values.begin() + r + 1);
142 const int expected_max = *std::max_element(values.begin() + l,
143 values.begin() + r + 1);
144 EXPECT_EQ(mn.query(l, r), expected_min);
145 EXPECT_EQ(mx.query(l, r), expected_max);
146 }
147}
148
150{
151 const std::vector<int> values = {5, 3, 7, 1, 9, 2, 8, 4, 6};
153
154 Array<int> arr;
155 for (const int x : values)
156 arr.append(x);
158
159 DynList<int> list;
160 for (const int x : values)
161 list.append(x);
163
164 Sparse_Table<int> from_init = {5, 3, 7, 1, 9, 2, 8, 4, 6};
165
166 for (size_t l = 0; l < values.size(); ++l)
167 for (size_t r = l; r < values.size(); ++r)
168 {
169 const int expected = *std::min_element(values.begin() + l,
170 values.begin() + r + 1);
171 EXPECT_EQ(from_vector.query(l, r), expected);
172 EXPECT_EQ(from_array.query(l, r), expected);
173 EXPECT_EQ(from_list.query(l, r), expected);
174 EXPECT_EQ(from_init.query(l, r), expected);
175 }
176}
177
179{
180 const std::vector<int> values = {12, 18, 24, 36, 60, 48, 30, 90, 15, 45};
182
183 for (size_t l = 0; l < values.size(); ++l)
184 for (size_t r = l; r < values.size(); ++r)
185 EXPECT_EQ(st.query(l, r), fold_range(values, l, r, Gcd_Op{}));
186}
187
189{
190 const std::vector<Bits> values = {{1}, {2}, {4}, {8}, {16}};
192
193 for (size_t l = 0; l < values.size(); ++l)
194 for (size_t r = l; r < values.size(); ++r)
195 EXPECT_EQ(st.query(l, r), fold_range(values, l, r, std::plus<Bits>{}));
196}
197
199{
200 const std::vector<int> base = {8, 6, 7, 5, 3, 0, 9};
201 Sparse_Table<int> st(base);
202
203 Array<int> vals = st.values();
204 ASSERT_EQ(vals.size(), base.size());
205 for (size_t i = 0; i < base.size(); ++i)
206 EXPECT_EQ(vals(i), base[i]);
207
209 EXPECT_EQ(copy.query(1, 5), 0);
210
211 Sparse_Table<int> moved = std::move(copy);
212 EXPECT_EQ(moved.query(2, 6), 0);
213
214 Sparse_Table<int> other = {100, 50, 75};
216
217 EXPECT_EQ(moved.size(), 3U);
218 EXPECT_EQ(moved.query(0, 2), 50);
219 EXPECT_EQ(other.size(), base.size());
220 EXPECT_EQ(other.query(0, 6), 0);
221}
222
224{
225 Sparse_Table<int> st = {1, 2, 3};
226
227 EXPECT_THROW(st.get(3), std::out_of_range);
228 EXPECT_THROW(st.query(0, 3), std::out_of_range);
229 EXPECT_THROW(st.query(2, 1), std::out_of_range);
230}
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:250
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
Sparse Table over an arbitrary associative and idempotent binary operation.
T get(const size_t i) const
Retrieve the value a[i] in O(1).
Array< T > values() const
Reconstruct all original values into an Array.
constexpr size_t size() const noexcept
Number of logical elements.
constexpr bool is_empty() const noexcept
True if the table contains no elements.
T query(const size_t l, const size_t r) const
Range query over [l, r] in O(1).
void swap(Gen_Sparse_Table &other) noexcept
Swap this table with other in O(1).
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1065
Minimal std::expected-style result type for C++20.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
#define TEST(name)
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
Gen_MultiPolynomial< C, M > operator+(const C &s, const Gen_MultiPolynomial< C, M > &p)
Scalar + polynomial (commutative).
bool operator==(const DynList< T > &l1, const DynList< T > &l2)
Equality operator for DynList.
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Definition ahAlgo.H:584
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
Sparse Table for range maximum queries.
Sparse Table for range minimum queries.
int operator()(const int &a, const int &b) const noexcept
gsl_rng * r
Sparse Table for static range queries in O(1).
constexpr auto min_lambda
DynList< int > l