Skip to content

Commit 66b254f

Browse files
committed
use generated int vectors as params for rmq, improve rmq tests
1 parent c07114e commit 66b254f

File tree

5 files changed

+89
-70
lines changed

5 files changed

+89
-70
lines changed

pysdsl/__init__.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ PYBIND11_MODULE(pysdsl, m)
4444

4545
auto csa_classes = add_csa(m);
4646

47-
auto rmq_classes_tuple = add_rmq_classes(m);
47+
auto rmq_classes_tuple = add_rmq_classes(m, iv_classes_as_params);
4848
auto& rmq_sparse_tables = std::get<0>(rmq_classes_tuple);
4949
auto& rmq_sada = std::get<1>(rmq_classes_tuple);
5050
auto& rmq_sct = std::get<2>(rmq_classes_tuple);

pysdsl/test/test_rmq.py

Lines changed: 0 additions & 44 deletions
This file was deleted.

pysdsl/types/rmq.hpp

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void add_rac_constructor(PybindClass& cls)
3535
} // namespace details
3636

3737

38-
// containers names
38+
// containers names for sparse
3939
namespace RAC_names {
4040
constexpr char INT_VECTOR_NAME[] = "IntVector",
4141
INT16_VECTOR_NAME[] = "Int16Vector";
@@ -80,7 +80,8 @@ struct add_rmq_sparse_table_functor {
8080
std::string key = std::string(t_min ? "Min" : "Max") + "_in_" + rac_name;
8181

8282
m.attr("rmq_sparse_tables").attr("__setitem__")(key, cls);
83-
m.attr("all_rmq_classes").attr("append")(cls);
83+
m.attr((std::string("all_range_") + (t_min ? "min" : "max") + "_classes").c_str())
84+
.attr("append")(cls);
8485

8586
return cls;
8687
}
@@ -111,7 +112,7 @@ struct add_rmq_sada_functor {
111112
.def("__call__",
112113
(size_type (RMQClass::*)(size_type, size_type) const)& RMQClass::operator(),
113114
(std::string("Returns an index of the ") + (t_min ? "minimal" : "maximal") +
114-
" value on the segment [l,r].").c_str());;
115+
" value on the segment [l,r].").c_str());;
115116

116117
detail::add_rac_constructor<decltype(cls), t_rac...>(cls);
117118

@@ -122,7 +123,8 @@ struct add_rmq_sada_functor {
122123
cls.doc() = doc;
123124

124125
m.attr("rmq_sada").attr("__setitem__")(t_min ? "Min" : "Max", cls);
125-
m.attr("all_rmq_classes").attr("append")(cls);
126+
m.attr((std::string("all_range_") + (t_min ? "min" : "max") + "_classes").c_str())
127+
.attr("append")(cls);
126128

127129
return cls;
128130
}
@@ -165,7 +167,8 @@ struct add_rmq_sct_functor {
165167
cls.doc() = doc;
166168

167169
m.attr("rmq_sct").attr("__setitem__")(t_min ? "Min" : "Max", cls);
168-
m.attr("all_rmq_classes").attr("append")(cls);
170+
m.attr((std::string("all_range_") + (t_min ? "min" : "max") + "_classes").c_str())
171+
.attr("append")(cls);
169172

170173
return cls;
171174
}
@@ -190,12 +193,21 @@ using general_rmq_sct = py::class_<
190193
typename sdsl::range_maximum_sct<>::type>::type>;
191194

192195

193-
inline auto add_rmq_classes(py::module& m)
196+
template <typename... Ts>
197+
static
198+
auto make_rmq_params(const std::tuple<py::class_<Ts>&...>& params) {
199+
return std::tuple<std::tuple<std::tuple<Ts...>, std::integral_constant<bool, true>>,
200+
std::tuple<std::tuple<Ts...>, std::integral_constant<bool, false>>>();
201+
}
202+
203+
204+
inline auto add_rmq_classes(py::module& m, auto params)
194205
{
195206
m.attr("rmq_sparse_tables") = py::dict();
196207
m.attr("rmq_sada") = py::dict();
197208
m.attr("rmq_sct") = py::dict();
198-
m.attr("all_rmq_classes") = py::list();
209+
m.attr("all_range_min_classes") = py::list();
210+
m.attr("all_range_max_classes") = py::list();
199211

200212
using rmq_support_sparse_table_params = std::tuple<
201213
std::tuple<sdsl::int_vector<>,
@@ -212,25 +224,11 @@ inline auto add_rmq_classes(py::module& m)
212224
std::integral_constant<bool, false>>
213225
>;
214226

215-
using rmq_sada_params = std::tuple<
216-
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
217-
std::integral_constant<bool, true>>,
218-
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
219-
std::integral_constant<bool, false>>
220-
>;
221-
222-
using rmq_sct_params = std::tuple<
223-
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
224-
std::integral_constant<bool, true>>,
225-
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
226-
std::integral_constant<bool, false>>
227-
>;
228-
229227
auto rmq_sparse_tables = for_each_in_tuple(rmq_support_sparse_table_params(),
230228
add_rmq_sparse_table_functor(m, doc_rmq_sparse_table));
231-
auto rmq_sada_classes = for_each_in_tuple(rmq_sada_params(),
229+
auto rmq_sada_classes = for_each_in_tuple(make_rmq_params(params),
232230
add_rmq_sada_functor(m, doc_rmq_sada));
233-
auto rmq_sct_classes = for_each_in_tuple(rmq_sct_params(),
231+
auto rmq_sct_classes = for_each_in_tuple(make_rmq_params(params),
234232
add_rmq_sct_functor(m, doc_rmq_sct));
235233

236234
return std::make_tuple(rmq_sparse_tables, rmq_sada_classes, rmq_sct_classes);

pysdsl/util/tupletricks.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ decltype(auto) for_each(const std::tuple<T...>& t, Function&& f) {
2424

2525
template<typename... T, typename Function>
2626
constexpr
27-
decltype(auto) for_each(std::tuple<T...>& t, Function&& f) {
27+
decltype(auto) for_each(std::tuple<T...>&& t, Function&& f) {
2828
return for_each_impl(t, f, std::index_sequence_for<T...>{}); }
2929

3030
template<typename P, typename Function, std::size_t... Is>
@@ -58,7 +58,7 @@ decltype(auto) for_each_in_tuple(const std::tuple<Ts...> &t, F f) {
5858

5959
template <typename... Ts, typename F>
6060
constexpr
61-
decltype(auto) for_each_in_tuple(std::tuple<Ts...> &t, F f) {
61+
decltype(auto) for_each_in_tuple(std::tuple<Ts...> &&t, F f) {
6262
return detail::for_each(t, f); }
6363

6464
template <typename... Ts, typename F>

tests/test_rmq.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import random
2+
import pytest
3+
4+
from pysdsl import Int8Vector, Int64Vector
5+
from pysdsl import rmq_sada, rmq_sct
6+
7+
8+
9+
10+
def _test_rmq(rmq_class, container_class, target):
11+
cont = container_class(50)
12+
a = []
13+
14+
for i in range(50):
15+
a.append(random.randint(0, 50))
16+
cont[i] = a[i]
17+
18+
rmq = rmq_class(cont)
19+
20+
for _ in range(50):
21+
l = random.randint(0, 49)
22+
r = random.randint(l, 49)
23+
24+
i = rmq(l, r)
25+
26+
assert cont[i] == target(a[l:r+1])
27+
28+
29+
30+
@pytest.mark.parametrize('container_class', (Int8Vector, Int64Vector))
31+
def test_rmq_sada(container_class):
32+
_test_rmq(rmq_sada['Min'], container_class, min)
33+
_test_rmq(rmq_sada['Max'], container_class, max)
34+
35+
36+
@pytest.mark.parametrize('container_class', (Int8Vector, Int64Vector))
37+
def test_rmq_sct(container_class):
38+
_test_rmq(rmq_sct['Min'], container_class, min)
39+
_test_rmq(rmq_sct['Max'], container_class, max)
40+
41+
42+
43+
@pytest.mark.parametrize("rmq_class", list(rmq_sada.values()) + list(rmq_sct.values()))
44+
def test_rmq_on_container_remove(rmq_class):
45+
cont = Int64Vector(3)
46+
47+
cont[0] = 1
48+
cont[1] = 2
49+
cont[2] = 3
50+
51+
rmq = rmq_class(cont)
52+
53+
ans1 = rmq(0, 2)
54+
55+
cont[0] = 3
56+
cont[1] = 2
57+
cont[2] = 1
58+
59+
ans2 = rmq(0, 2)
60+
assert ans1 == ans2
61+
62+
cont = None
63+
64+
ans2 = rmq(0, 2)
65+
assert ans1 == ans2

0 commit comments

Comments
 (0)