93 cout << " Testing: " << name << "... " << flush; \
99 cout << "\033[32mPASS\033[0m\n"; \
105 cout << "\033[31mFAIL\033[0m (" << msg << ")\n"; \
108# define CHECK(cond, msg) \
110 if (!(cond)) { FAIL(msg); return; } \
113# define CHECK_EQ(a, b, msg) \
117 ss << msg << " (expected " << (b) << ", got " << (a) << ")"; \
123# define CHECK_THROWS(ExType, expr, msg) \
125 bool caught = false; \
126 try { expr; } catch (const ExType &) { caught = true; } \
127 if (!caught) { FAIL(msg); return; } \
132 chrono::high_resolution_clock::time_point
start;
137 auto end = chrono::high_resolution_clock::now();
138 return chrono::duration<double, milli>(end -
start).count();
153 for (
size_t i =
l + 1; i <= r; ++i)
162 for (
size_t i =
l + 1; i <= r; ++i)
170 for (
size_t i =
l + 1; i <= r; ++i)
178 for (
size_t i =
l + 1; i <= r; ++i)
186 for (
size_t i =
l + 1; i <= r; ++i)
201 CHECK(st.is_empty(),
"is_empty");
202 CHECK_EQ(st.num_levels(), 0u,
"levels");
205 "get(0) on empty should throw");
207 "query(0,0) on empty should throw");
214 TEST(
"single element — min");
226 TEST(
"single element — max");
234 TEST(
"two elements — min/max");
248 TEST(
"all-equal array (n=100)");
249 vector<int> v(100, 77);
251 for (
size_t l = 0;
l < 100;
l += 13)
252 for (
size_t r =
l; r < 100; r += 17)
259 TEST(
"sorted ascending (min = leftmost, max = rightmost)");
261 iota(v.begin(), v.end(), 1);
273 TEST(
"sorted descending");
275 for (
int i = 0; i < 50; ++i) v[i] = 50 - i;
287 TEST(
"power-of-two sizes (1, 2, 4, 8, 16, 32, 64)");
288 for (
size_t sz : {1u, 2u, 4u, 8u, 16u, 32u, 64u})
291 for (
size_t i = 0; i < sz; ++i)
292 v[i] =
static_cast<int>(
rng() % 10000);
303 TEST(
"non-power-of-two sizes (3, 5, 7, 10, 13, 17, 31, 33, 63, 65, 100)");
304 for (
size_t sz : {3u, 5u, 7u, 10u, 13u, 17u, 31u, 33u, 63u, 65u, 100u})
307 for (
size_t i = 0; i < sz; ++i)
308 v[i] =
static_cast<int>(
rng() % 10000);
323 TEST(
"known array min queries");
342 TEST(
"known array max queries");
356 TEST(
"get() returns correct element for all positions");
357 vector<int> v = {10, -3, 42, 0, 7, -99, 88, 1};
359 for (
size_t i = 0; i < v.size(); ++i)
366 TEST(
"values() reconstructs original array");
367 vector<int> v = {10, -3, 42, 0, 7, -99, 88, 1, 55, -20};
371 for (
size_t i = 0; i < v.size(); ++i)
382 TEST(
"stress: Sparse_Table (min) n=200, 5000 random queries");
383 const size_t N = 200;
387 for (
size_t i = 0; i <
N; ++i)
388 v[i] =
static_cast<int>(
rng() % 200001) - 100000;
393 for (
int q = 0; q <
Q; ++q)
395 size_t a = dist(
rng), b = dist(
rng);
396 if (a > b)
swap(a, b);
402 ss <<
"query(" << a <<
"," << b <<
"): expected " <<
expected
403 <<
", got " <<
got <<
" (q=" << q <<
")";
413 TEST(
"stress: Max_Sparse_Table (max) n=200, 5000 random queries");
414 const size_t N = 200;
418 for (
size_t i = 0; i <
N; ++i)
419 v[i] =
static_cast<int>(
rng() % 200001) - 100000;
424 for (
int q = 0; q <
Q; ++q)
426 size_t a = dist(
rng), b = dist(
rng);
427 if (a > b)
swap(a, b);
433 ss <<
"query(" << a <<
"," << b <<
"): expected " <<
expected
444 TEST(
"stress: Sparse_Table (min) n=10000, 50000 random queries");
445 const size_t N = 10000;
449 for (
size_t i = 0; i <
N; ++i)
450 v[i] =
static_cast<int>(
rng());
455 for (
int q = 0; q <
Q; ++q)
457 size_t a = dist(
rng), b = dist(
rng);
458 if (a > b)
swap(a, b);
464 ss <<
"query(" << a <<
"," << b <<
"): expected " <<
expected
475 TEST(
"stress: all point queries match original (n=500)");
476 const size_t N = 500;
478 for (
size_t i = 0; i <
N; ++i)
479 v[i] =
static_cast<int>(
rng());
482 for (
size_t i = 0; i <
N; ++i)
492 TEST(
"stress: ALL (l,r) pairs for n=80 — exhaustive");
495 for (
size_t i = 0; i <
N; ++i)
496 v[i] =
static_cast<int>(
rng() % 1000) - 500;
501 for (
size_t l = 0;
l <
N; ++
l)
502 for (
size_t r =
l; r <
N; ++r)
509 ss <<
"min query(" <<
l <<
"," << r <<
"): expected "
517 ss <<
"max query(" <<
l <<
"," << r <<
"): expected "
556 TEST(
"GCD sparse table — known values");
568 TEST(
"GCD sparse table — random stress n=300, 10000 queries");
569 const size_t N = 300;
574 for (
size_t i = 0; i <
N; ++i)
580 for (
int q = 0; q <
Q; ++q)
583 if (a > b)
swap(a, b);
589 ss <<
"gcd query(" << a <<
"," << b <<
"): expected "
600 TEST(
"AND sparse table — random stress n=200, 5000 queries");
601 const size_t N = 200;
605 for (
size_t i = 0; i <
N; ++i)
606 v[i] =
static_cast<int>(
rng() & 0x7FFFFFFF);
611 for (
int q = 0; q <
Q; ++q)
613 size_t a = dist(
rng), b = dist(
rng);
614 if (a > b)
swap(a, b);
620 ss <<
"AND query(" << a <<
"," << b <<
"): expected "
631 TEST(
"OR sparse table — random stress n=200, 5000 queries");
632 const size_t N = 200;
636 for (
size_t i = 0; i <
N; ++i)
637 v[i] =
static_cast<int>(
rng() & 0x7FFFFFFF);
642 for (
int q = 0; q <
Q; ++q)
644 size_t a = dist(
rng), b = dist(
rng);
645 if (a > b)
swap(a, b);
651 ss <<
"OR query(" << a <<
"," << b <<
"): expected "
666 TEST(
"construct from Array<int>");
677 TEST(
"construct from std::vector<int>");
678 vector<int> v = {9, 1, 7, 3, 5};
687 TEST(
"construct from DynList<int>");
697 TEST(
"construct from initializer_list");
706 TEST(
"construct with uniform init_val (n=50, val=-5)");
716 TEST(
"all constructors produce identical query results");
717 vector<int>
raw = {15, 8, 23, 4, 42, 1, 17, 9, 30, 6};
720 for (
size_t i = 0; i <
raw.
size(); ++i)
724 for (
size_t i = 0; i <
raw.
size(); ++i)
733 for (
int q = 0; q < 200; ++q)
735 size_t a = dist(
rng), b = dist(
rng);
736 if (a > b)
swap(a, b);
751 TEST(
"copy constructor");
764 TEST(
"move constructor");
776 TEST(
"copy assignment");
788 TEST(
"move assignment");
816 TEST(
"query throws out_of_range when r >= n");
819 "should throw for r=5, n=5");
821 "should throw for r=100");
827 TEST(
"query throws out_of_range when l > r");
830 "should throw for l=3, r=2");
836 TEST(
"get throws out_of_range when i >= n");
839 "should throw for i=3, n=3");
841 "should throw for i=1000");
847 TEST(
"boundary queries that should NOT throw");
865 TEST(
"negative values");
876 TEST(
"INT_MIN/INT_MAX values");
889 TEST(
"double values (including negative and close values)");
895 CHECK(
mx.query(0, 4) == 3.14,
"max double");
901 TEST(
"stress: double min/max n=500, 5000 queries");
902 const size_t N = 500;
907 for (
size_t i = 0; i <
N; ++i)
914 for (
int q = 0; q <
Q; ++q)
917 if (a > b)
swap(a, b);
923 ss <<
"double query(" << a <<
"," << b <<
") mismatch";
933 TEST(
"long long values");
935 1LL << 60, -(1LL << 59), 0
LL, 1LL << 50, -(1LL << 62)
940 1LL << 60, -(1LL << 59), 0
LL, 1LL << 50, -(1LL << 62)
942 CHECK_EQ(
mx.query(0, 4), 1LL << 60,
"max ll");
952 TEST(
"performance: build n=1,000,000");
953 const size_t N = 1000000;
955 for (
size_t i = 0; i <
N; ++i)
956 v[i] =
static_cast<int>(
rng());
960 double ms =
timer.elapsed_ms();
964 CHECK(
ms < 5000.0,
"build should complete in < 5s");
970 TEST(
"performance: 1,000,000 queries on n=100,000");
971 const size_t N = 100000;
972 const int Q = 1000000;
975 for (
size_t i = 0; i <
N; ++i)
976 v[i] =
static_cast<int>(
rng());
981 volatile int sink = 0;
984 for (
int q = 0; q <
Q; ++q)
986 size_t a = dist(
rng), b = dist(
rng);
987 if (a > b)
swap(a, b);
988 sink = st.
query(a, b);
990 double ms =
timer.elapsed_ms();
993 CHECK(
ms < 10000.0,
"1M queries should complete in < 10s");
1000 TEST(
"performance: build n=5,000,000");
1001 const size_t N = 5000000;
1003 for (
size_t i = 0; i <
N; ++i)
1004 v[i] =
static_cast<int>(
rng());
1008 double ms =
timer.elapsed_ms();
1012 size_t a = 1000, b = 4999000;
1018 CHECK(
ms < 20000.0,
"build should complete in < 20s");
1028 TEST(
"overlapping sub-ranges give correct result (idempotency)");
1032 vector<int> v = {10, 3, 7, 1, 8, 5, 2, 9, 4, 6};
1056 TEST(
"num_levels() = floor(log2(n)) + 1");
1057 for (
size_t n : {1u, 2u, 3u, 4u, 5u, 7u, 8u, 15u, 16u, 17u, 100u, 1024u})
1059 vector<int> v(n, 0);
1061 size_t expected =
static_cast<size_t>(std::bit_width(n));
1080 TEST(
"self copy-assignment (st = st)");
1090 for (
size_t i = 0; i < st.
size(); ++i)
1097 TEST(
"self swap (st.swap(st))");
1109 TEST(
"get(i) == query(i,i) for all i (n=200)");
1110 const size_t n = 200;
1112 for (
auto & x : v) x =
static_cast<int>(
rng() % 10000);
1114 for (
size_t i = 0; i < n; ++i)
1121 TEST(
"idempotent overlap split: min(query(l,m), query(m',r)) == query(l,r)");
1122 const size_t n = 60;
1124 for (
auto & x : v) x =
static_cast<int>(
rng() % 1000);
1127 for (
size_t l = 0;
l < n; ++
l)
1128 for (
size_t r =
l; r < n; ++r)
1132 for (
size_t m =
l; m < r; ++m)
1143 TEST(
"disjoint split: min(query(l,m), query(m+1,r)) == query(l,r)");
1144 const size_t n = 80;
1146 for (
auto & x : v) x =
static_cast<int>(
rng() % 1000);
1149 for (
size_t l = 0;
l < n; ++
l)
1150 for (
size_t r =
l + 1; r < n; ++r)
1153 for (
size_t m =
l; m < r; ++m)
1164 TEST(
"adversarial: zigzag pattern (alternating high/low)");
1166 const size_t n = 100;
1168 for (
size_t i = 0; i < n; ++i)
1169 v[i] = (i % 2 == 0) ? 1000 : 1;
1172 for (
size_t l = 0;
l < n; ++
l)
1173 for (
size_t r =
l; r < n; r += 7)
1180 TEST(
"adversarial: single outlier among equals");
1181 const size_t n = 128;
1184 vector<int> v(n, 100);
1188 for (
size_t l = 0;
l < n; ++
l)
1189 for (
size_t r =
l; r < n; r += 13)
1200 TEST(
"adversarial: plateau with single dip at every position");
1201 const size_t n = 50;
1204 vector<int> v(n, 999);
1209 CHECK_EQ(st.
query(0, n - 1), 0,
"full range must find dip");
1221 TEST(
"sliding window queries (width=10) across n=200");
1222 const size_t n = 200;
1223 const size_t w = 10;
1225 for (
auto & x : v) x =
static_cast<int>(
rng() % 1000);
1228 for (
size_t l = 0;
l +
w - 1 < n; ++
l)
1230 "sliding window mismatch");
1242 seed =
static_cast<unsigned>(
atoi(
argv[1]));
1244 seed =
static_cast<unsigned>(
1245 chrono::high_resolution_clock::now().time_since_epoch().count());
1249 cout <<
"╔══════════════════════════════════════════════════════════════╗\n";
1250 cout <<
"║ Sparse Table Test Suite ║\n";
1251 cout <<
"║ Testing Gen_Sparse_Table, Sparse_Table, Max_Sparse ║\n";
1252 cout <<
"╚══════════════════════════════════════════════════════════════╝\n";
1253 cout <<
" Seed: " << seed <<
"\n\n";
1255 cout <<
"=== 1. Edge Cases ===\n";
1266 cout <<
"\n=== 2. Basic Correctness ===\n";
1272 cout <<
"\n=== 3. Brute-Force Stress Tests ===\n";
1279 cout <<
"\n=== 4. Custom Idempotent Operations ===\n";
1285 cout <<
"\n=== 5. Construction from All Container Types ===\n";
1293 cout <<
"\n=== 6. Copy, Move, Swap ===\n";
1300 cout <<
"\n=== 7. Exception Safety ===\n";
1306 cout <<
"\n=== 8. Numerical Edge Cases ===\n";
1313 cout <<
"\n=== 9. Performance ===\n";
1318 cout <<
"\n=== 10. Idempotency & Structure ===\n";
1322 cout <<
"\n=== 11. Robustness & Algebraic Properties ===\n";
1334 cout <<
"══════════════════════════════════════════════════════════════\n";
1339 cout <<
" — \033[32mALL PASS\033[0m";
1341 cout <<
"══════════════════════════════════════════════════════════════\n";
Simple dynamic array with automatic resizing and functional operations.
T & append(const T &data)
Append a copy of data
Dynamic singly linked list with functional programming support.
T & append(const T &item)
Append a new item by copy.
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).
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.
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.
double elapsed_ms() const
chrono::high_resolution_clock::time_point start
__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)
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_min_function > > min(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Main namespace for Aleph-w library functions.
T & swap(T &t1, T &t2)
Generic swap using object's swap method.
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
std::decay_t< typename HeadC::Item_Type > T
Itor min_element(Itor beg, const Itor &end, CompFunc op=CompFunc())
Find the minimum element in a range.
DynList< T > maps(const C &c, Op op)
Classic map operation.
void test_stress_max_small()
void test_adversarial_plateau_with_dip()
void test_known_max_array()
void test_values_reconstruction()
void test_adversarial_single_outlier()
void test_overlapping_ranges_idempotent()
void test_query_l_greater_than_r()
void test_get_out_of_range()
void test_double_stress()
void test_stress_min_medium()
void test_performance_build_large()
#define CHECK_EQ(a, b, msg)
void test_bitwise_or_stress()
T brute_max(const vector< T > &v, size_t l, size_t r)
void test_move_constructor()
void test_single_element_max()
void test_double_values()
void test_disjoint_split_min()
#define CHECK_THROWS(ExType, expr, msg)
void test_known_min_array()
void test_stress_all_pairs_small()
void test_construct_uniform_value()
int brute_and(const vector< int > &v, size_t l, size_t r)
void test_construct_from_array()
void test_performance_build()
void test_move_assignment()
int brute_or(const vector< int > &v, size_t l, size_t r)
void test_long_long_values()
void test_power_of_two_sizes()
void test_stress_all_point_queries()
void test_copy_constructor()
void test_sliding_window()
void test_negative_values()
void test_non_power_of_two_sizes()
void test_construct_from_vector()
void test_stress_min_small()
void test_query_r_out_of_range()
void test_all_constructors_agree()
void test_copy_assignment()
void test_bitwise_and_stress()
void test_sorted_ascending()
void test_single_element()
void test_get_equals_point_query()
void test_self_copy_assignment()
void test_performance_queries()
T brute_min(const vector< T > &v, size_t l, size_t r)
void test_construct_from_initlist()
void test_sorted_descending()
void test_get_all_elements()
void test_boundary_queries_valid()
void test_construct_from_dynlist()
void test_adversarial_zigzag()
int brute_gcd(const vector< int > &v, size_t l, size_t r)
void test_num_levels_correctness()
void test_idempotent_overlap_split()
Sparse Table for range maximum queries.
Sparse Table for range minimum queries.
int operator()(const int &a, const int &b) const noexcept
int operator()(const int &a, const int &b) const noexcept
int operator()(const int &a, const int &b) const noexcept
Dynamic array container with automatic resizing.
Alias for htlist.H (DynList implementation).
Sparse Table for static range queries in O(1).