14#include <lagrange/python/binding.h>
27#define LA_SAFE_VECTOR_SETTER(prop, arg_type) \
28 nanobind::for_setter(nanobind::sig("def " prop "(self, arg: " arg_type ", /) -> None"))
30NAMESPACE_BEGIN(NB_NAMESPACE)
34 rv_policy::value Policy = rv_policy::automatic_reference_v,
36class_<Vector> bind_safe_vector(handle scope,
const char* name,
Args&&... args)
38 using ValueRef =
typename detail::iterator_access<typename Vector::iterator>::result_type;
39 using Value = std::decay_t<ValueRef>;
40 using ValueType =
typename Value::element_type;
43 std::is_same_v<std::shared_ptr<ValueType>,
Value>,
44 "bind_safe_vector(): Value type must be a std::shared_ptr<>");
47 !detail::is_base_caster_v<detail::make_caster<Value>> ||
48 detail::is_copy_constructible_v<Value> ||
49 (Policy != rv_policy::automatic_reference_v && Policy != rv_policy::copy_v),
50 "bind_safe_vector(): the generated __getitem__ would copy elements, so the "
51 "element type must be copy-constructible");
53 handle cl_cur = type<Vector>();
54 if (cl_cur.is_valid()) {
56 return borrow<class_<Vector>>(cl_cur);
59 auto cl = class_<Vector>(scope, name, std::forward<Args>(args)...)
60 .def(init<>(),
"Default constructor")
62 .def(
"__len__", [](
const Vector& v) {
return v.size(); })
66 [](
const Vector& v) {
return !v.empty(); },
67 "Check whether the vector is nonempty")
71 [](handle_t<Vector> h) {
return steal<str>(detail::repr_list(h.ptr())); })
76 return make_iterator<Policy>(
79 v.Vector::Super::begin(),
80 v.Vector::Super::end());
86 [](Vector& v, Py_ssize_t i) -> ValueRef {
87 return v.Vector::Super::operator[](detail::wrap(i, v.size()));
89 rv_policy::policy_tag<Policy>{})
91 .def(
"clear", [](Vector& v) { v.clear(); },
"Remove all items from list.");
93 if constexpr (detail::is_copy_constructible_v<Value>) {
94 cl.def(init<const Vector&>(),
"Copy constructor");
98 [](Vector* v, typed<iterable, Value> seq) {
100 v->reserve(len_hint(seq));
101 for (handle h : seq) v->Vector::Super::push_back(cast<Value>(h));
103 "Construct from an iterable object");
105 implicitly_convertible<iterable, Vector>();
109 [](Vector& v,
const Value& value) { v.Vector::Super::push_back(value); },
110 "Append `arg` to the end of the list.")
114 [](Vector& v, Py_ssize_t i,
const Value& x) {
115 if (i < 0) i += (Py_ssize_t)v.size();
116 if (i < 0 || (
size_t)i > v.size())
throw index_error();
117 v.insert(v.Vector::Super::begin() + i, x);
119 "Insert object `arg1` before index `arg0`.")
123 [](Vector& v, Py_ssize_t i) {
124 size_t index = detail::wrap(i, v.size());
125 Value result = std::move(v.Vector::Super::operator[](index));
126 v.erase(v.Vector::Super::begin() + index);
130 "Remove and return item at `index` (default last).")
134 [](Vector& v,
const Vector& src) {
136 v.Vector::Super::end(),
137 src.Vector::Super::begin(),
138 src.Vector::Super::end());
140 "Extend `self` by appending elements from `arg`.")
144 [](Vector& v, Py_ssize_t i,
const Value& value) {
145 v.Vector::Super::operator[](detail::wrap(i, v.size())) = value;
150 [](Vector& v, Py_ssize_t i) {
151 v.erase(v.Vector::Super::begin() + detail::wrap(i, v.size()));
156 [](
const Vector& v,
const slice& slice) -> Vector* {
157 auto [start, stop, step, length] = slice.compute(v.size());
159 seq->reserve(length);
161 for (
size_t i = 0; i < length; ++i) {
162 seq->Vector::Super::push_back(v.Vector::Super::operator[](start));
171 [](Vector& v,
const slice& slice,
const Vector& value) {
172 auto [start, stop, step, length] = slice.compute(v.size());
174 if (length != value.size())
176 "The left and right hand side of the slice "
177 "assignment have mismatched sizes!");
179 for (
size_t i = 0; i < length; ++i) {
180 v.Vector::Super::operator[](start) = value.Vector::Super::operator[](i);
185 .def(
"__delitem__", [](Vector& v,
const slice& slice) {
186 auto [start, stop, step, length] = slice.compute(v.size());
187 if (length == 0)
return;
189 stop = start + (length - 1) * step;
191 std::swap(start, stop);
196 v.erase(v.Vector::Super::begin() + start, v.Vector::Super::begin() + stop + 1);
198 for (
size_t i = 0; i < length; ++i) {
199 v.erase(v.Vector::Super::begin() + stop);
206 if constexpr (detail::is_equality_comparable_v<Value>) {
207 cl.def(self == self, sig(
"def __eq__(self, arg: object, /) -> bool"))
208 .def(self != self, sig(
"def __ne__(self, arg: object, /) -> bool"))
212 [](
const Vector& v,
const Value& x) {
213 return std::find(v.Vector::Super::begin(), v.Vector::Super::end(), x) !=
214 v.Vector::Super::end();
219 [](
const Vector&, handle) {
return false; })
223 [](
const Vector& v,
const Value& x) {
224 return std::count(v.Vector::Super::begin(), v.Vector::Super::end(), x);
226 "Return number of occurrences of `arg`.")
230 [](Vector& v,
const Value& x) {
231 auto p = std::find(v.Vector::Super::begin(), v.Vector::Super::end(), x);
232 if (p != v.Vector::Super::end())
237 "Remove first occurrence of `arg`.");
243NAMESPACE_END(NB_NAMESPACE)
@ Value
Values that are not attached to a specific element.
Definition AttributeFwd.h:42
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
Type alias for one-dimensional column Eigen vectors.
Definition views.h:79
Definition project.cpp:27