29 template<
typename A,
typename B>
31 return !(*it).first || !(*it).second;
34 template <
typename PythonType>
37 throw py::value_error(
"Please provide at least 5 elements for testing.");
39 auto checks = py::list();
40 auto assert_equal = [&checks](py::handle a, py::handle b) {
41 auto result = PyObject_RichCompareBool(a.ptr(), b.ptr(), Py_EQ);
42 if (result == -1) {
throw py::error_already_set(); }
43 checks.append(result != 0);
68 checks.append(
static_cast<std::size_t>(
x.end() -
x.begin()) ==
x.size());
69 checks.append((
x.begin() +
static_cast<std::ptrdiff_t
>(
x.size())) ==
x.end());
70 checks.append(
x.begin() <
x.end());
79 Sliceable(
int n):
size(n) {}
83 py::class_<Sliceable>(
m,
"Sliceable")
85 .def(
"__getitem__",[](
const Sliceable &s, py::slice
slice) {
87 if (!
slice.
compute(s.size, &start, &stop, &step, &slicelength))
88 throw py::error_already_set();
89 int istart =
static_cast<int>(start);
90 int istop =
static_cast<int>(stop);
91 int istep =
static_cast<int>(step);
99 Sequence(
size_t size) : m_size(
size) {
101 m_data =
new float[
size];
102 memset(m_data, 0,
sizeof(
float) *
size);
104 Sequence(
const std::vector<float> &
value) : m_size(
value.size()) {
106 m_data =
new float[m_size];
107 memcpy(m_data, &
value[0],
sizeof(
float) * m_size);
109 Sequence(
const Sequence &s) : m_size(s.m_size) {
111 m_data =
new float[m_size];
112 memcpy(m_data, s.m_data,
sizeof(
float)*m_size);
114 Sequence(Sequence &&s) : m_size(s.m_size), m_data(s.m_data) {
122 Sequence &operator=(
const Sequence &s) {
126 m_data =
new float[m_size];
127 memcpy(m_data, s.m_data,
sizeof(
float)*m_size);
133 Sequence &operator=(Sequence &&s) {
146 if (m_size != s.size())
return false;
147 for (
size_t i = 0;
i < m_size; ++
i)
148 if (m_data[
i] != s[
i])
152 bool operator!=(
const Sequence &s)
const {
return !
operator==(s); }
154 float operator[](
size_t index)
const {
return m_data[index]; }
155 float &operator[](
size_t index) {
return m_data[index]; }
157 bool contains(
float v)
const {
158 for (
size_t i = 0;
i < m_size; ++
i)
164 Sequence reversed()
const {
165 Sequence result(m_size);
166 for (
size_t i = 0;
i < m_size; ++
i)
167 result[m_size -
i - 1] = m_data[
i];
171 size_t size()
const {
return m_size; }
173 const float *
begin()
const {
return m_data; }
174 const float *
end()
const {
return m_data+m_size; }
180 py::class_<Sequence>(
m,
"Sequence")
181 .def(py::init<size_t>())
182 .def(
py::init<
const std::vector<float>&>())
184 .def(
"__getitem__", [](
const Sequence &s,
size_t i) {
185 if (
i >= s.size())
throw py::index_error();
188 .
def(
"__setitem__", [](Sequence &s,
size_t i,
float v) {
189 if (
i >= s.size())
throw py::index_error();
194 .def(
"__iter__", [](
const Sequence &s) {
return py::make_iterator(s.begin(), s.end()); },
195 py::keep_alive<0, 1>() )
196 .
def(
"__contains__", [](
const Sequence &s,
float v) {
return s.contains(v); })
197 .
def(
"__reversed__", [](
const Sequence &s) -> Sequence {
return s.reversed(); })
199 .
def(
"__getitem__", [](
const Sequence &s, py::slice
slice) -> Sequence* {
200 size_t start, stop, step, slicelength;
201 if (!
slice.
compute(s.size(), &start, &stop, &step, &slicelength))
202 throw py::error_already_set();
203 auto *seq =
new Sequence(slicelength);
204 for (
size_t i = 0;
i < slicelength; ++
i) {
205 (*seq)[
i] = s[start]; start += step;
209 .
def(
"__setitem__", [](Sequence &s, py::slice
slice,
const Sequence &
value) {
210 size_t start, stop, step, slicelength;
211 if (!
slice.
compute(s.size(), &start, &stop, &step, &slicelength))
212 throw py::error_already_set();
213 if (slicelength !=
value.size())
214 throw std::runtime_error(
"Left and right hand size of slice assignment have different sizes!");
215 for (
size_t i = 0;
i < slicelength; ++
i) {
216 s[start] =
value[
i]; start += step;
220 .
def(py::self == py::self)
221 .def(py::self != py::self)
230 StringMap() =
default;
231 StringMap(std::unordered_map<std::string, std::string>
init)
234 void set(std::string key, std::string val) { map[key] = val; }
235 std::string get(std::string key)
const {
return map.at(key); }
236 size_t size()
const {
return map.size(); }
238 std::unordered_map<std::string, std::string> map;
240 decltype(map.cbegin())
begin()
const {
return map.cbegin(); }
241 decltype(map.cend())
end()
const {
return map.cend(); }
243 py::class_<StringMap>(
m,
"StringMap")
245 .def(
py::init<std::unordered_map<std::string, std::string>>())
246 .def(
"__getitem__", [](
const StringMap &map, std::string key) {
247 try {
return map.get(key); }
248 catch (
const std::out_of_range&) {
249 throw py::key_error(
"key '" + key +
"' does not exist");
252 .
def(
"__setitem__", &StringMap::set)
255 py::keep_alive<0, 1>())
257 py::keep_alive<0, 1>())
264 const std::pair<int, int>*
begin()
const {
return data_.data(); }
266 std::vector<std::pair<int, int>> data_;
268 py::class_<IntPairs>(
m,
"IntPairs")
269 .def(
py::init<std::vector<std::pair<int, int>>>())
270 .def(
"nonzero", [](
const IntPairs& s) {
272 }, py::keep_alive<0, 1>())
273 .
def(
"nonzero_keys", [](
const IntPairs& s) {
275 }, py::keep_alive<0, 1>())
284 struct PySequenceIterator {
285 PySequenceIterator(
const Sequence &seq, py::object
ref) : seq(seq),
ref(
ref) { }
288 if (index == seq.size())
289 throw py::stop_iteration();
298 py::class_<PySequenceIterator>(seq,
"Iterator")
299 .def(
"__iter__", [](PySequenceIterator &it) -> PySequenceIterator& {
return it; })
300 .
def(
"__next__", &PySequenceIterator::next);
302 On the actual Sequence
object, the
iterator would be constructed as follows:
303 .def(
"__iter__", [](py::object s) {
return PySequenceIterator(s.cast<
const Sequence &>(), s); })
307 m.def(
"object_to_list", [](py::object o) {
309 for (
auto item : o) {
315 m.def(
"iterator_to_list", [](py::iterator it) {
317 while (it != py::iterator::sentinel()) {
325 m.def(
"sequence_length", [](py::sequence seq) {
return seq.size(); });
328 m.def(
"count_none", [](py::object o) {
329 return std::count_if(o.begin(), o.end(), [](py::handle h) { return h.is_none(); });
332 m.def(
"find_none", [](py::object o) {
333 auto it = std::find_if(o.begin(), o.end(), [](py::handle h) { return h.is_none(); });
334 return it->is_none();
337 m.def(
"count_nonzeros", [](py::dict d) {
338 return std::count_if(d.begin(), d.end(), [](std::pair<py::handle, py::handle> p) {
339 return p.second.cast<int>() != 0;
343 m.def(
"tuple_iterator", &test_random_access_iterator<py::tuple>);
344 m.def(
"list_iterator", &test_random_access_iterator<py::list>);
345 m.def(
"sequence_iterator", &test_random_access_iterator<py::sequence>);
349 m.def(
"iterator_passthrough", [](py::iterator s) -> py::iterator {
355 static std::vector<int>
list = { 1, 2, 3 };
356 m.def(
"make_iterator_1", []() {
return py::make_iterator<py::return_value_policy::copy>(
list); });
357 m.def(
"make_iterator_2", []() {
return py::make_iterator<py::return_value_policy::automatic>(
list); });