Skip to content

Commit 9347e8c

Browse files
committed
rmq
1 parent c59007e commit 9347e8c

File tree

5 files changed

+279
-2
lines changed

5 files changed

+279
-2
lines changed

pysdsl/__init__.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "types/intvector.hpp"
1717
#include "types/suffixarray.hpp"
1818
#include "types/wavelet.hpp"
19+
#include "types/rmq.hpp"
1920

2021
namespace py = pybind11;
2122

@@ -40,6 +41,12 @@ PYBIND11_MODULE(pysdsl, m)
4041

4142
auto csa_classes = add_csa(m);
4243

44+
// new
45+
auto rmq_classes_tuple = add_rmq_classes(m);
46+
auto& rmq_sparse_tables = std::get<0>(rmq_classes_tuple);
47+
auto& rmq_sada = std::get<1>(rmq_classes_tuple);
48+
auto& rmq_sct = std::get<2>(rmq_classes_tuple);
49+
4350
for_each_in_tuple(iv_classes, make_inits_many_functor(iv_classes));
4451
for_each_in_tuple(iv_classes, make_inits_many_functor(enc_classes));
4552
for_each_in_tuple(iv_classes,

pysdsl/docstrings.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,7 @@ const char* doc_csa_wt(
258258
"A class for the Compressed Suffix Array (CSA) based on a Wavelet Tree "
259259
"(WT) of the Burrow Wheeler Transform of the original text."
260260
);
261+
262+
const char* doc_rmq_sada("");
263+
264+
const char* doc_rmq_sparse_table("");

pysdsl/types/rmq.hpp

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <tuple>
5+
#include <utility>
6+
7+
#include <pybind11/pybind11.h>
8+
9+
#include <sdsl/rmq_support_sparse_table.hpp>
10+
#include <sdsl/rmq_succinct_sada.hpp>
11+
12+
#include "operations/sizes.hpp"
13+
#include "operations/iteration.hpp"
14+
#include "util/tupletricks.hpp"
15+
#include "docstrings.hpp"
16+
#include "io.hpp"
17+
#include "calc.hpp"
18+
19+
20+
21+
namespace detail {
22+
// adds constructors of t_rac... containers
23+
template <typename PybindClass, typename... t_rac>
24+
typename std::enable_if<sizeof...(t_rac) == 0>::type add_rac_constructor(const PybindClass&) {}
25+
26+
template <typename PybindClass, typename t_rac_head, typename... t_rac_tail>
27+
void add_rac_constructor(PybindClass& cls) {
28+
cls.def(py::init([](const t_rac_head* rac) {
29+
return typename PybindClass::type(rac);
30+
}));
31+
add_rac_constructor<PybindClass, t_rac_tail...>(cls);
32+
}
33+
}
34+
35+
// containers names
36+
namespace RAC_names {
37+
const char INT_VECTOR_NAME[] = "IntVector",
38+
INT16_VECTOR_NAME[] = "Int16Vector";
39+
}
40+
41+
42+
struct add_rmq_sparse_table_functor {
43+
py::module& m;
44+
const char* doc;
45+
46+
constexpr add_rmq_sparse_table_functor(py::module& m, const char* doc = nullptr)
47+
: m(m), doc(doc) {}
48+
49+
template <typename t_rac, const char* rac_name, bool t_min>
50+
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+
55+
std::string name =
56+
std::string("Range") + (t_min ? "Min" : "Max") + "QuerySparseTable_for_" + rac_name;
57+
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)
62+
.def("__call__",
63+
(typename T::size_type
64+
(T::*)(typename T::size_type, typename T::size_type) const)& T::operator());
65+
66+
add_sizes(cls);
67+
add_description(cls);
68+
69+
// load takes two params
70+
// add_serialization(cls);
71+
72+
return cls;
73+
}
74+
};
75+
76+
77+
struct add_rmq_sada_functor {
78+
py::module& m;
79+
const char* doc;
80+
81+
constexpr add_rmq_sada_functor(py::module& m, const char* doc = nullptr)
82+
: m(m), doc(doc) {}
83+
84+
85+
template <typename... t_rac, bool t_min>
86+
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;
90+
91+
std::string name =
92+
std::string("Range") + (t_min ? "Min" : "Max") + "QuerySuccintSada";
93+
94+
auto cls = py::class_<T>(m, name.c_str())
95+
.def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size)
96+
.def(py::init())
97+
.def("__call__",
98+
(typename T::size_type
99+
(T::*)(typename T::size_type, typename T::size_type) const)& T::operator());
100+
101+
detail::add_rac_constructor<decltype(cls), t_rac...>(cls);
102+
103+
add_sizes(cls);
104+
add_description(cls);
105+
add_serialization(cls);
106+
107+
return cls;
108+
}
109+
};
110+
111+
112+
struct add_rmq_sct_functor {
113+
py::module& m;
114+
const char* doc;
115+
116+
constexpr add_rmq_sct_functor(py::module& m, const char* doc = nullptr)
117+
: m(m), doc(doc) {}
118+
119+
120+
template <typename... t_rac, bool t_min>
121+
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;
125+
126+
std::string name =
127+
std::string("Range") + (t_min ? "Min" : "Max") + "QuerySuccintSct";
128+
129+
auto cls = py::class_<T>(m, name.c_str())
130+
.def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size)
131+
.def(py::init())
132+
.def("__call__",
133+
(typename T::size_type
134+
(T::*)(typename T::size_type, typename T::size_type) const)& T::operator());
135+
136+
detail::add_rac_constructor<decltype(cls), t_rac...>(cls);
137+
138+
add_sizes(cls);
139+
add_description(cls);
140+
add_serialization(cls);
141+
142+
return cls;
143+
}
144+
};
145+
146+
147+
// generalized (constants -> typenames) template for usage with GeneralSubsetFunctor
148+
template <typename t_rac, typename t_min_ic>
149+
using general_rmq_sparse_table = py::class_<sdsl::rmq_support_sparse_table<t_rac, t_min_ic::value>>;
150+
151+
template <typename t_min_ic>
152+
using general_rmq_sada = py::class_<
153+
typename std::conditional<t_min_ic::value,
154+
sdsl::rmq_succinct_sada<>,
155+
typename sdsl::range_maximum_support_sada<>::type>::type>;
156+
157+
template <typename t_min_ic>
158+
using general_rmq_sct = py::class_<
159+
typename std::conditional<t_min_ic::value,
160+
sdsl::rmq_succinct_sct<>,
161+
typename sdsl::range_maximum_sct<>::type>::type>;
162+
163+
164+
inline auto add_rmq_classes(py::module& m) {
165+
m.attr("rmq_sparse_table") = py::dict();
166+
167+
168+
using rmq_support_sparse_table_params = std::tuple<
169+
std::tuple<sdsl::int_vector<>,
170+
std::integral_constant<const char*, RAC_names::INT_VECTOR_NAME>,
171+
std::integral_constant<bool, true>>,
172+
std::tuple<sdsl::int_vector<>,
173+
std::integral_constant<const char*, RAC_names::INT_VECTOR_NAME>,
174+
std::integral_constant<bool, false>>,
175+
std::tuple<sdsl::int_vector<16>,
176+
std::integral_constant<const char*, RAC_names::INT16_VECTOR_NAME>,
177+
std::integral_constant<bool, true>>,
178+
std::tuple<sdsl::int_vector<16>,
179+
std::integral_constant<const char*, RAC_names::INT16_VECTOR_NAME>,
180+
std::integral_constant<bool, false>>
181+
>;
182+
183+
using rmq_sada_params = std::tuple<
184+
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
185+
std::integral_constant<bool, true>>,
186+
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
187+
std::integral_constant<bool, false>>
188+
>;
189+
190+
using rmq_sct_params = std::tuple<
191+
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
192+
std::integral_constant<bool, true>>,
193+
std::tuple<std::tuple<sdsl::int_vector<>, sdsl::int_vector<16>>,
194+
std::integral_constant<bool, false>>
195+
>;
196+
197+
auto rmq_sparse_tables = for_each_in_tuple(rmq_support_sparse_table_params(),
198+
add_rmq_sparse_table_functor(m, doc_rmq_sparse_table));
199+
auto rmq_sada_classes = for_each_in_tuple(rmq_sada_params(),
200+
add_rmq_sada_functor(m, doc_rmq_sada));
201+
auto rmq_sct_classes = for_each_in_tuple(rmq_sct_params(),
202+
add_rmq_sct_functor(m, doc_rmq_sada));
203+
204+
////////////// as params //////////////////////
205+
using rmq_support_sparse_table_as_params = std::tuple<
206+
std::tuple<sdsl::int_vector<>, std::integral_constant<bool, true>>,
207+
std::tuple<sdsl::int_vector<>, std::integral_constant<bool, false>>
208+
>;
209+
210+
auto rmq_sparse_tables_as_params = for_each_in_tuple(rmq_support_sparse_table_as_params(),
211+
make_general_sybset_functor<general_rmq_sparse_table>(rmq_sparse_tables));
212+
///////////////////////////////////////////////
213+
214+
return std::make_tuple(rmq_sparse_tables, rmq_sada_classes, rmq_sct_classes);
215+
}

pysdsl/util/tupletricks.hpp

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ decltype(auto) for_each_impl(P&& t, Function&& f, std::index_sequence<Is...>) {
1414

1515
template<typename P, typename Function, std::size_t... Is>
1616
constexpr
17-
decltype(auto) for_each_impl(P& t, Function&& f, std::index_sequence<Is...>) {
17+
decltype(auto) for_each_impl(const P& t, Function&& f, std::index_sequence<Is...>) {
1818
return std::make_tuple(f(std::get<Is>(t))...); }
1919

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

30+
template<typename P, typename Function, std::size_t... Is>
31+
constexpr
32+
decltype(auto) forward_each_impl(P&& t, Function&& f, std::index_sequence<Is...>) {
33+
return std::forward_as_tuple(f(std::get<Is>(t))...); }
34+
35+
template<typename P, typename Function, std::size_t... Is>
36+
constexpr
37+
decltype(auto) forward_each_impl(const P& t, Function&& f, std::index_sequence<Is...>) {
38+
return std::forward_as_tuple(f(std::get<Is>(t))...); }
39+
40+
template<typename... T, typename Function>
41+
constexpr
42+
decltype(auto) forward_each(const std::tuple<T...>& t, Function&& f) {
43+
return forward_each_impl(t, f, std::index_sequence_for<T...>{}); }
44+
45+
template<typename... T, typename Function>
46+
constexpr
47+
decltype(auto) forward_each(std::tuple<T...>& t, Function&& f) {
48+
return forward_each_impl(t, f, std::index_sequence_for<T...>{}); }
49+
3050
} // namespace detail
3151

3252

@@ -40,3 +60,34 @@ template <typename... Ts, typename F>
4060
constexpr
4161
decltype(auto) for_each_in_tuple(std::tuple<Ts...> &t, F f) {
4262
return detail::for_each(t, f); }
63+
64+
template <typename... Ts, typename F>
65+
constexpr
66+
decltype(auto) forward_each_in_tuple(const std::tuple<Ts...> &t, F f) {
67+
return detail::forward_each(t, f); }
68+
69+
70+
template <typename... Ts, typename F>
71+
constexpr
72+
decltype(auto) forward_each_in_tuple(std::tuple<Ts...> &t, F f) {
73+
return detail::forward_each(t, f); }
74+
75+
76+
// subset functor
77+
template <template <typename...> typename general_template, typename... Ts>
78+
struct GeneralSubsetFunctor {
79+
std::tuple<Ts...>& tpl;
80+
81+
constexpr GeneralSubsetFunctor(std::tuple<Ts...>& tpl) noexcept
82+
: tpl(tpl) {}
83+
84+
template <typename... Args>
85+
auto& operator()(std::tuple<Args...>) const {
86+
return std::get<general_template<Args...>>(tpl);
87+
}
88+
};
89+
90+
template <template <typename...> typename general_template, typename... Ts>
91+
auto make_general_sybset_functor(std::tuple<Ts...>& tpl) {
92+
return GeneralSubsetFunctor<general_template, Ts...>(tpl);
93+
}

sdsl-lite

0 commit comments

Comments
 (0)