Skip to content

Commit 83e74d3

Browse files
committed
style, rmq tests, rmq docstrings
1 parent c04333b commit 83e74d3

File tree

4 files changed

+124
-54
lines changed

4 files changed

+124
-54
lines changed

pysdsl/__init__.cpp

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

4545
auto csa_classes = add_csa(m);
4646

47-
// new
4847
auto rmq_classes_tuple = add_rmq_classes(m);
4948
auto& rmq_sparse_tables = std::get<0>(rmq_classes_tuple);
5049
auto& rmq_sada = std::get<1>(rmq_classes_tuple);

pysdsl/docstrings.hpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,17 @@ const char* doc_csa_wt(
259259
"(WT) of the Burrow Wheeler Transform of the original text."
260260
);
261261

262-
const char* doc_rmq_sada("");
262+
const char* doc_rmq_sada(
263+
"A class to support range minimum or range maximum queries on a random access container "
264+
"in constant time and 4n+o(n) bits space."
265+
);
266+
267+
const char* doc_rmq_sparse_table(
268+
"A class to support range minimum or range maximum queries on a random access container "
269+
"in constant time and O( n log^2(n) ) bits space."
270+
);
263271

264-
const char* doc_rmq_sparse_table("");
272+
const char* doc_rmq_sct(
273+
"A class to support range minimum or range maximum queries on a random access container "
274+
"in constant time and 2n+o(n) bits space."
275+
);

pysdsl/test/test_rmq.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from pysdsl import IntVector, Int16Vector
2+
3+
from pysdsl import rmq_sada, rmq_sct, rmq_sparse_tables
4+
5+
import random
6+
7+
8+
def _test_rmq(rmq_class, container_class, target):
9+
cont = container_class(50)
10+
a = []
11+
12+
for i in range(50):
13+
a.append(random.randint(0, 50))
14+
cont[i] = a[i]
15+
16+
rmq = rmq_class(cont)
17+
18+
for _ in range(50):
19+
l = random.randint(0, 49)
20+
r = random.randint(l, 49)
21+
22+
i = rmq(l, r)
23+
24+
assert(cont[i] == target(a[l:r+1]))
25+
26+
27+
def test_rmq_sada():
28+
_test_rmq(rmq_sada['Min'], IntVector, min)
29+
_test_rmq(rmq_sada['Max'], IntVector, max)
30+
_test_rmq(rmq_sada['Min'], Int16Vector, min)
31+
_test_rmq(rmq_sada['Max'], Int16Vector, max)
32+
33+
def test_rmq_sct():
34+
_test_rmq(rmq_sct['Min'], IntVector, min)
35+
_test_rmq(rmq_sct['Max'], IntVector, max)
36+
_test_rmq(rmq_sct['Min'], Int16Vector, min)
37+
_test_rmq(rmq_sct['Max'], Int16Vector, max)
38+
39+
def test_rmq_sparse_table():
40+
_test_rmq(rmq_sparse_tables['Min_in_IntVector'], IntVector, min)
41+
_test_rmq(rmq_sparse_tables['Max_in_IntVector'], IntVector, max)
42+
_test_rmq(rmq_sparse_tables['Min_in_Int16Vector'], Int16Vector, min)
43+
_test_rmq(rmq_sparse_tables['Max_in_Int16Vector'], Int16Vector, max)

pysdsl/types/rmq.hpp

Lines changed: 68 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,21 @@ template <typename PybindClass, typename... t_rac>
2424
typename std::enable_if<sizeof...(t_rac) == 0>::type add_rac_constructor(const PybindClass&) {}
2525

2626
template <typename PybindClass, typename t_rac_head, typename... t_rac_tail>
27-
void add_rac_constructor(PybindClass& cls) {
27+
void add_rac_constructor(PybindClass& cls)
28+
{
2829
cls.def(py::init([](const t_rac_head* rac) {
2930
return typename PybindClass::type(rac);
3031
}));
3132
add_rac_constructor<PybindClass, t_rac_tail...>(cls);
3233
}
33-
}
34+
35+
} // namespace details
36+
3437

3538
// containers names
3639
namespace RAC_names {
37-
const char INT_VECTOR_NAME[] = "IntVector",
38-
INT16_VECTOR_NAME[] = "Int16Vector";
40+
constexpr char INT_VECTOR_NAME[] = "IntVector",
41+
INT16_VECTOR_NAME[] = "Int16Vector";
3942
}
4043

4144

@@ -48,27 +51,35 @@ struct add_rmq_sparse_table_functor {
4851

4952
template <typename t_rac, const char* rac_name, bool t_min>
5053
decltype(auto) operator()(std::tuple<t_rac,
51-
std::integral_constant<const char*, rac_name>,
52-
std::integral_constant<bool, t_min>>) {
53-
using T = sdsl::rmq_support_sparse_table<t_rac, t_min>;
54+
std::integral_constant<const char*, rac_name>,
55+
std::integral_constant<bool, t_min>>)
56+
{
57+
using Table = sdsl::rmq_support_sparse_table<t_rac, t_min>;
58+
using size_type = typename Table::size_type;
5459

5560
std::string name =
5661
std::string("Range") + (t_min ? "Min" : "Max") + "QuerySparseTable_for_" + rac_name;
5762

58-
auto cls = py::class_<T>(m, name.c_str())
59-
.def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size)
60-
.def(py::init([](const t_rac* rac) {return T(rac);}))
61-
.def("set_vector", &T::set_vector)
63+
auto cls = py::class_<Table>(m, name.c_str())
64+
.def_property_readonly("size", (size_type(Table::*)(void) const)& Table::size)
65+
.def(py::init([](const t_rac* rac) {return Table(rac);}))
66+
.def("set_vector", &Table::set_vector)
6267
.def("__call__",
63-
(typename T::size_type
64-
(T::*)(typename T::size_type, typename T::size_type) const)& T::operator());
68+
(size_type (Table::*)(size_type, size_type) const)& Table::operator());
6569

6670
add_sizes(cls);
6771
add_description(cls);
6872

6973
// load takes two params
7074
// add_serialization(cls);
7175

76+
cls.doc() = doc;
77+
78+
std::string key = std::string(t_min ? "Min" : "Max") + "_in_" + rac_name;
79+
80+
m.attr("rmq_sparse_tables").attr("__setitem__")(key, cls);
81+
m.attr("all_rmq_classes").attr("append")(cls);
82+
7283
return cls;
7384
}
7485
};
@@ -84,26 +95,32 @@ struct add_rmq_sada_functor {
8495

8596
template <typename... t_rac, bool t_min>
8697
decltype(auto) operator()(std::tuple<std::tuple<t_rac...>,
87-
std::integral_constant<bool, t_min>>) {
88-
using T = typename std::conditional<t_min, sdsl::rmq_succinct_sada<>,
89-
typename sdsl::range_maximum_support_sada<>::type>::type;
98+
std::integral_constant<bool, t_min>>)
99+
{
100+
using RMQClass = typename std::conditional<t_min, sdsl::rmq_succinct_sada<>,
101+
typename sdsl::range_maximum_support_sada<>::type>::type;
102+
using size_type = typename RMQClass::size_type;
90103

91104
std::string name =
92105
std::string("Range") + (t_min ? "Min" : "Max") + "QuerySuccintSada";
93106

94-
auto cls = py::class_<T>(m, name.c_str())
95-
.def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size)
107+
auto cls = py::class_<RMQClass>(m, name.c_str())
108+
.def_property_readonly("size", (size_type (RMQClass::*)(void) const)& RMQClass::size)
96109
.def(py::init())
97110
.def("__call__",
98-
(typename T::size_type
99-
(T::*)(typename T::size_type, typename T::size_type) const)& T::operator());
111+
(size_type (RMQClass::*)(size_type, size_type) const)& RMQClass::operator());
100112

101113
detail::add_rac_constructor<decltype(cls), t_rac...>(cls);
102114

103115
add_sizes(cls);
104116
add_description(cls);
105117
add_serialization(cls);
106118

119+
cls.doc() = doc;
120+
121+
m.attr("rmq_sada").attr("__setitem__")(t_min ? "Min" : "Max", cls);
122+
m.attr("all_rmq_classes").attr("append")(cls);
123+
107124
return cls;
108125
}
109126
};
@@ -119,19 +136,20 @@ struct add_rmq_sct_functor {
119136

120137
template <typename... t_rac, bool t_min>
121138
decltype(auto) operator()(std::tuple<std::tuple<t_rac...>,
122-
std::integral_constant<bool, t_min>>) {
123-
using T = typename std::conditional<t_min, sdsl::rmq_succinct_sct<>,
124-
typename sdsl::range_maximum_sct<>::type>::type;
139+
std::integral_constant<bool, t_min>>)
140+
{
141+
using RMQClass = typename std::conditional<t_min, sdsl::rmq_succinct_sct<>,
142+
typename sdsl::range_maximum_sct<>::type>::type;
143+
using size_type = typename RMQClass::size_type;
125144

126145
std::string name =
127146
std::string("Range") + (t_min ? "Min" : "Max") + "QuerySuccintSct";
128147

129-
auto cls = py::class_<T>(m, name.c_str())
130-
.def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size)
148+
auto cls = py::class_<RMQClass>(m, name.c_str())
149+
.def_property_readonly("size", (size_type (RMQClass::*)(void) const)& RMQClass::size)
131150
.def(py::init())
132151
.def("__call__",
133-
(typename T::size_type
134-
(T::*)(typename T::size_type, typename T::size_type) const)& T::operator());
152+
(size_type (RMQClass::*)(size_type, size_type) const)& RMQClass::operator());
135153

136154

137155
detail::add_rac_constructor<decltype(cls), t_rac...>(cls);
@@ -140,31 +158,40 @@ struct add_rmq_sct_functor {
140158
add_description(cls);
141159
add_serialization(cls);
142160

161+
cls.doc() = doc;
162+
163+
m.attr("rmq_sct").attr("__setitem__")(t_min ? "Min" : "Max", cls);
164+
m.attr("all_rmq_classes").attr("append")(cls);
165+
143166
return cls;
144167
}
145168
};
146169

147170

148171
// generalized (constants -> typenames) template for usage with GeneralSubsetFunctor
149-
template <typename t_rac, typename t_min_ic>
150-
using general_rmq_sparse_table = py::class_<sdsl::rmq_support_sparse_table<t_rac, t_min_ic::value>>;
172+
template <typename t_rac, typename t_min_integral_constant>
173+
using general_rmq_sparse_table =
174+
py::class_<sdsl::rmq_support_sparse_table<t_rac, t_min_integral_constant::value>>;
151175

152-
template <typename t_min_ic>
176+
template <typename t_min_integral_constant>
153177
using general_rmq_sada = py::class_<
154-
typename std::conditional<t_min_ic::value,
155-
sdsl::rmq_succinct_sada<>,
156-
typename sdsl::range_maximum_support_sada<>::type>::type>;
178+
typename std::conditional<t_min_integral_constant::value,
179+
sdsl::rmq_succinct_sada<>,
180+
typename sdsl::range_maximum_support_sada<>::type>::type>;
157181

158-
template <typename t_min_ic>
182+
template <typename t_min_integral_constant>
159183
using general_rmq_sct = py::class_<
160-
typename std::conditional<t_min_ic::value,
161-
sdsl::rmq_succinct_sct<>,
162-
typename sdsl::range_maximum_sct<>::type>::type>;
163-
184+
typename std::conditional<t_min_integral_constant::value,
185+
sdsl::rmq_succinct_sct<>,
186+
typename sdsl::range_maximum_sct<>::type>::type>;
164187

165-
inline auto add_rmq_classes(py::module& m) {
166-
m.attr("rmq_sparse_table") = py::dict();
167188

189+
inline auto add_rmq_classes(py::module& m)
190+
{
191+
m.attr("rmq_sparse_tables") = py::dict();
192+
m.attr("rmq_sada") = py::dict();
193+
m.attr("rmq_sct") = py::dict();
194+
m.attr("all_rmq_classes") = py::list();
168195

169196
using rmq_support_sparse_table_params = std::tuple<
170197
std::tuple<sdsl::int_vector<>,
@@ -200,17 +227,7 @@ inline auto add_rmq_classes(py::module& m) {
200227
auto rmq_sada_classes = for_each_in_tuple(rmq_sada_params(),
201228
add_rmq_sada_functor(m, doc_rmq_sada));
202229
auto rmq_sct_classes = for_each_in_tuple(rmq_sct_params(),
203-
add_rmq_sct_functor(m, doc_rmq_sada));
204-
205-
////////////// as params //////////////////////
206-
using rmq_support_sparse_table_as_params = std::tuple<
207-
std::tuple<sdsl::int_vector<>, std::integral_constant<bool, true>>,
208-
std::tuple<sdsl::int_vector<>, std::integral_constant<bool, false>>
209-
>;
210-
211-
auto rmq_sparse_tables_as_params = for_each_in_tuple(rmq_support_sparse_table_as_params(),
212-
make_general_sybset_functor<general_rmq_sparse_table>(rmq_sparse_tables));
213-
///////////////////////////////////////////////
230+
add_rmq_sct_functor(m, doc_rmq_sct));
214231

215232
return std::make_tuple(rmq_sparse_tables, rmq_sada_classes, rmq_sct_classes);
216233
}

0 commit comments

Comments
 (0)