Browse Source

update: enhance Cases module of python-ffi

legacy
Dnomd343 3 weeks ago
parent
commit
f75fbdf182
  1. 11
      src/core_ffi/python_ffi/binder/cases.cc
  2. 2
      src/core_ffi/python_ffi/include/binder.h
  3. 24
      src/core_ffi/python_ffi/include/py_ffi/cases.h
  4. 41
      src/core_ffi/python_ffi/wrapper/cases.cc

11
src/core_ffi/python_ffi/binder/cases.cc

@ -1,13 +1,16 @@
#include "binder.h" #include "binder.h"
void bind_cases(const py::module_ &m) { void bind_cases(const py::module_ &mod) {
py::class_<PyCases>(m, "Cases") py::class_<PyCases>(mod, "Cases")
.def(py::self == py::self) .def(py::self == py::self)
.def("__len__", &PyCases::size) .def("__len__", &PyCases::size)
.def("__repr__", &PyCases::repr) .def("__repr__", &PyCases::repr)
.def("__getitem__", &PyCases::at) .def("__getitem__", &PyCases::at)
.def("__iter__", &PyCases::codes, py::keep_alive<0, 1>()); .def("__iter__", &PyCases::iter, py::keep_alive<0, 1>())
.def_property_readonly_static("all_cases", [](const py::object&) {
return PyCases::all_cases();
});
py::class_<PyCasesIter>(m, "CasesIter") py::class_<PyCasesIter>(mod, "CasesIter")
.def("__next__", &PyCasesIter::next); .def("__next__", &PyCasesIter::next);
} }

2
src/core_ffi/python_ffi/include/binder.h

@ -20,7 +20,7 @@ using klotski::ffi::PyGroupUnion;
using klotski::ffi::PyGroup; using klotski::ffi::PyGroup;
using klotski::ffi::PyFastCal; using klotski::ffi::PyFastCal;
void bind_cases(const py::module_ &m); void bind_cases(const py::module_ &mod);
void bind_short_code(const py::module_ &m); void bind_short_code(const py::module_ &m);
void bind_common_code(const py::module_ &m); void bind_common_code(const py::module_ &m);

24
src/core_ffi/python_ffi/include/py_ffi/cases.h

@ -3,7 +3,8 @@
#pragma once #pragma once
#include <variant> #include <variant>
#include <ranges/ranges.h>
#include "ranges/ranges.h"
#include "py_ffi/common_code.h" #include "py_ffi/common_code.h"
@ -14,14 +15,14 @@ using cases::RangesUnion;
class PyCasesIter { class PyCasesIter {
public: public:
/// Construct from RangesUnion reference. /// Construct from RangesUnion reference.
explicit PyCasesIter(const RangesUnion &data); explicit PyCasesIter(const RangesUnion &data) noexcept;
/// Get the next CommonCode or throw a stop_iteration exception. /// Get the next CommonCode or throw `stop_iteration` exception.
PyCommonCode next(); PyCommonCode next();
private: private:
uint8_t head_ {0}; size_t index_ {0};
uint32_t index_ {0}; uint64_t head_ {0};
const RangesUnion &data_; const RangesUnion &data_;
}; };
@ -29,8 +30,6 @@ class PyCases {
public: public:
PyCases() = delete; PyCases() = delete;
// TODO: add `all_cases` interface
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Constructing from r-value. /// Constructing from r-value.
@ -45,18 +44,21 @@ public:
[[nodiscard]] size_t size() const noexcept; [[nodiscard]] size_t size() const noexcept;
/// Get CommonCode iterator of cases. /// Get CommonCode iterator of cases.
[[nodiscard]] PyCasesIter codes() const noexcept; [[nodiscard]] PyCasesIter iter() const noexcept;
/// Get the CommonCode of the specified index. /// Get the CommonCode of the specified index.
[[nodiscard]] PyCommonCode at(size_t index) const; // TODO: allow `-1` index [[nodiscard]] PyCommonCode at(int32_t index) const;
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Export all klotski cases.
static PyCases all_cases() noexcept;
/// Wrapper of `__repr__` method in Python. /// Wrapper of `__repr__` method in Python.
static std::string repr(const PyCases &cases) noexcept; static std::string repr(const PyCases &cases) noexcept;
/// Compare the cases contents of two PyCases. /// Compare the cases contents of two PyCases.
friend constexpr auto operator==(const PyCases &lhs, const PyCases &rhs); friend constexpr auto operator==(const PyCases &lhs, const PyCases &rhs) noexcept;
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
@ -75,7 +77,7 @@ private:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
}; };
constexpr auto operator==(const PyCases &lhs, const PyCases &rhs) { constexpr auto operator==(const PyCases &lhs, const PyCases &rhs) noexcept {
return lhs.data_ref() == rhs.data_ref(); return lhs.data_ref() == rhs.data_ref();
} }

41
src/core_ffi/python_ffi/wrapper/cases.cc

@ -6,17 +6,16 @@
namespace py = pybind11; namespace py = pybind11;
using namespace klotski::ffi; using namespace klotski::ffi;
using klotski::cases::AllCases;
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
PyCasesIter::PyCasesIter(const RangesUnion &data) : data_(data) {} PyCasesIter::PyCasesIter(const RangesUnion &data) noexcept : data_(data) {}
PyCommonCode PyCasesIter::next() { PyCommonCode PyCasesIter::next() {
while (head_ < 16) { while (head_ < 16) {
const auto &ranges = data_.ranges(head_); if (const auto &ranges = data_.ranges(head_); index_ < ranges.size()) {
if (index_ < ranges.size()) { return std::bit_cast<PyCommonCode>((head_ << 32) | ranges[index_++]);
auto code = (static_cast<uint64_t>(head_) << 32) | ranges[index_++];
return std::bit_cast<PyCommonCode>(code);
} }
index_ = 0, ++head_; index_ = 0, ++head_;
} }
@ -26,36 +25,26 @@ PyCommonCode PyCasesIter::next() {
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
size_t PyCases::size() const noexcept { size_t PyCases::size() const noexcept {
size_t num = 0; return data_ref().size();
for (const auto &x : data_ref()) { // TODO: fetch from RangesUnion.size()
num += x.size();
}
return num;
} }
PyCasesIter PyCases::codes() const noexcept { PyCasesIter PyCases::iter() const noexcept {
return PyCasesIter(data_ref()); return PyCasesIter(data_ref());
} }
PyCommonCode PyCases::at(size_t index) const { PyCommonCode PyCases::at(const int32_t index) const {
if (index >= size()) { const auto size_ = static_cast<int32_t>(size());
if (index >= size_ || index < -size_) {
throw py::index_error("cases index out of range"); throw py::index_error("cases index out of range");
} }
const auto code = data_ref()[index < 0 ? index + size_ : index];
uint64_t head = 0; return std::bit_cast<PyCommonCode>(code);
for (;;) {
if (index >= data_ref().ranges(head).size()) {
index -= data_ref().ranges(head).size();
++head;
} else {
break;
}
} }
uint32_t range = data_ref().ranges(head)[index];
// TODO: fetch from RangesUnion[] // ----------------------------------------------------------------------------------------- //
const auto code = CommonCode::unsafe_create(head << 32 | range);
return std::bit_cast<PyCommonCode>(code); PyCases PyCases::all_cases() noexcept {
return from_ref(AllCases::instance().fetch());
} }
std::string PyCases::repr(const PyCases &cases) noexcept { std::string PyCases::repr(const PyCases &cases) noexcept {

Loading…
Cancel
Save