diff --git a/pysdsl/__init__.cpp b/pysdsl/__init__.cpp index 49d3dcc..952c1b1 100644 --- a/pysdsl/__init__.cpp +++ b/pysdsl/__init__.cpp @@ -16,6 +16,7 @@ #include "types/intvector.hpp" #include "types/suffixarray.hpp" #include "types/wavelet.hpp" +#include "types/rmq.hpp" namespace py = pybind11; @@ -40,6 +41,12 @@ PYBIND11_MODULE(pysdsl, m) auto csa_classes = add_csa(m); + // new + auto rmq_classes_tuple = add_rmq_classes(m); + auto& rmq_sparse_tables = std::get<0>(rmq_classes_tuple); + auto& rmq_sada = std::get<1>(rmq_classes_tuple); + auto& rmq_sct = std::get<2>(rmq_classes_tuple); + for_each_in_tuple(iv_classes, make_inits_many_functor(iv_classes)); for_each_in_tuple(iv_classes, make_inits_many_functor(enc_classes)); for_each_in_tuple(iv_classes, diff --git a/pysdsl/docstrings.hpp b/pysdsl/docstrings.hpp index 5995f37..0396ca0 100644 --- a/pysdsl/docstrings.hpp +++ b/pysdsl/docstrings.hpp @@ -258,3 +258,7 @@ const char* doc_csa_wt( "A class for the Compressed Suffix Array (CSA) based on a Wavelet Tree " "(WT) of the Burrow Wheeler Transform of the original text." ); + +const char* doc_rmq_sada(""); + +const char* doc_rmq_sparse_table(""); diff --git a/pysdsl/types/rmq.hpp b/pysdsl/types/rmq.hpp new file mode 100644 index 0000000..e1f3c27 --- /dev/null +++ b/pysdsl/types/rmq.hpp @@ -0,0 +1,215 @@ +#pragma once + +#include +#include +#include + +#include + +#include +#include + +#include "operations/sizes.hpp" +#include "operations/iteration.hpp" +#include "util/tupletricks.hpp" +#include "docstrings.hpp" +#include "io.hpp" +#include "calc.hpp" + + + +namespace detail { +// adds constructors of t_rac... containers +template +typename std::enable_if::type add_rac_constructor(const PybindClass&) {} + +template +void add_rac_constructor(PybindClass& cls) { + cls.def(py::init([](const t_rac_head* rac) { + return typename PybindClass::type(rac); + })); + add_rac_constructor(cls); +} +} + +// containers names +namespace RAC_names { + const char INT_VECTOR_NAME[] = "IntVector", + INT16_VECTOR_NAME[] = "Int16Vector"; +} + + +struct add_rmq_sparse_table_functor { + py::module& m; + const char* doc; + + constexpr add_rmq_sparse_table_functor(py::module& m, const char* doc = nullptr) + : m(m), doc(doc) {} + + template + decltype(auto) operator()(std::tuple, + std::integral_constant>) { + using T = sdsl::rmq_support_sparse_table; + + std::string name = + std::string("Range") + (t_min ? "Min" : "Max") + "QuerySparseTable_for_" + rac_name; + + auto cls = py::class_(m, name.c_str()) + .def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size) + .def(py::init([](const t_rac* rac) {return T(rac);})) + .def("set_vector", &T::set_vector) + .def("__call__", + (typename T::size_type + (T::*)(typename T::size_type, typename T::size_type) const)& T::operator()); + + add_sizes(cls); + add_description(cls); + + // load takes two params + // add_serialization(cls); + + return cls; + } +}; + + +struct add_rmq_sada_functor { + py::module& m; + const char* doc; + + constexpr add_rmq_sada_functor(py::module& m, const char* doc = nullptr) + : m(m), doc(doc) {} + + + template + decltype(auto) operator()(std::tuple, + std::integral_constant>) { + using T = typename std::conditional, + typename sdsl::range_maximum_support_sada<>::type>::type; + + std::string name = + std::string("Range") + (t_min ? "Min" : "Max") + "QuerySuccintSada"; + + auto cls = py::class_(m, name.c_str()) + .def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size) + .def(py::init()) + .def("__call__", + (typename T::size_type + (T::*)(typename T::size_type, typename T::size_type) const)& T::operator()); + + detail::add_rac_constructor(cls); + + add_sizes(cls); + add_description(cls); + add_serialization(cls); + + return cls; + } +}; + + +struct add_rmq_sct_functor { + py::module& m; + const char* doc; + + constexpr add_rmq_sct_functor(py::module& m, const char* doc = nullptr) + : m(m), doc(doc) {} + + + template + decltype(auto) operator()(std::tuple, + std::integral_constant>) { + using T = typename std::conditional, + typename sdsl::range_maximum_sct<>::type>::type; + + std::string name = + std::string("Range") + (t_min ? "Min" : "Max") + "QuerySuccintSct"; + + auto cls = py::class_(m, name.c_str()) + .def_property_readonly("size", (typename T::size_type(T::*)(void) const)& T::size) + .def(py::init()) + .def("__call__", + (typename T::size_type + (T::*)(typename T::size_type, typename T::size_type) const)& T::operator()); + + detail::add_rac_constructor(cls); + + add_sizes(cls); + add_description(cls); + add_serialization(cls); + + return cls; + } +}; + + +// generalized (constants -> typenames) template for usage with GeneralSubsetFunctor +template +using general_rmq_sparse_table = py::class_>; + +template +using general_rmq_sada = py::class_< + typename std::conditional, + typename sdsl::range_maximum_support_sada<>::type>::type>; + +template +using general_rmq_sct = py::class_< + typename std::conditional, + typename sdsl::range_maximum_sct<>::type>::type>; + + +inline auto add_rmq_classes(py::module& m) { + m.attr("rmq_sparse_table") = py::dict(); + + + using rmq_support_sparse_table_params = std::tuple< + std::tuple, + std::integral_constant, + std::integral_constant>, + std::tuple, + std::integral_constant, + std::integral_constant>, + std::tuple, + std::integral_constant, + std::integral_constant>, + std::tuple, + std::integral_constant, + std::integral_constant> + >; + + using rmq_sada_params = std::tuple< + std::tuple, sdsl::int_vector<16>>, + std::integral_constant>, + std::tuple, sdsl::int_vector<16>>, + std::integral_constant> + >; + + using rmq_sct_params = std::tuple< + std::tuple, sdsl::int_vector<16>>, + std::integral_constant>, + std::tuple, sdsl::int_vector<16>>, + std::integral_constant> + >; + + auto rmq_sparse_tables = for_each_in_tuple(rmq_support_sparse_table_params(), + add_rmq_sparse_table_functor(m, doc_rmq_sparse_table)); + auto rmq_sada_classes = for_each_in_tuple(rmq_sada_params(), + add_rmq_sada_functor(m, doc_rmq_sada)); + auto rmq_sct_classes = for_each_in_tuple(rmq_sct_params(), + add_rmq_sct_functor(m, doc_rmq_sada)); + + ////////////// as params ////////////////////// + using rmq_support_sparse_table_as_params = std::tuple< + std::tuple, std::integral_constant>, + std::tuple, std::integral_constant> + >; + + auto rmq_sparse_tables_as_params = for_each_in_tuple(rmq_support_sparse_table_as_params(), + make_general_sybset_functor(rmq_sparse_tables)); + /////////////////////////////////////////////// + + return std::make_tuple(rmq_sparse_tables, rmq_sada_classes, rmq_sct_classes); +} diff --git a/pysdsl/util/tupletricks.hpp b/pysdsl/util/tupletricks.hpp index 2070080..ebc554a 100644 --- a/pysdsl/util/tupletricks.hpp +++ b/pysdsl/util/tupletricks.hpp @@ -14,7 +14,7 @@ decltype(auto) for_each_impl(P&& t, Function&& f, std::index_sequence) { template constexpr -decltype(auto) for_each_impl(P& t, Function&& f, std::index_sequence) { +decltype(auto) for_each_impl(const P& t, Function&& f, std::index_sequence) { return std::make_tuple(f(std::get(t))...); } template @@ -27,6 +27,26 @@ constexpr decltype(auto) for_each(std::tuple& t, Function&& f) { return for_each_impl(t, f, std::index_sequence_for{}); } +template +constexpr +decltype(auto) forward_each_impl(P&& t, Function&& f, std::index_sequence) { + return std::forward_as_tuple(f(std::get(t))...); } + +template +constexpr +decltype(auto) forward_each_impl(const P& t, Function&& f, std::index_sequence) { + return std::forward_as_tuple(f(std::get(t))...); } + +template +constexpr +decltype(auto) forward_each(const std::tuple& t, Function&& f) { + return forward_each_impl(t, f, std::index_sequence_for{}); } + +template +constexpr +decltype(auto) forward_each(std::tuple& t, Function&& f) { + return forward_each_impl(t, f, std::index_sequence_for{}); } + } // namespace detail @@ -40,3 +60,34 @@ template constexpr decltype(auto) for_each_in_tuple(std::tuple &t, F f) { return detail::for_each(t, f); } + +template +constexpr +decltype(auto) forward_each_in_tuple(const std::tuple &t, F f) { + return detail::forward_each(t, f); } + + +template +constexpr +decltype(auto) forward_each_in_tuple(std::tuple &t, F f) { + return detail::forward_each(t, f); } + + +// subset functor +template