Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#pragma once
#include <pybind11/pybind11.h>
namespace py = pybind11;
#include "RawIterator.h"
template< typename Array, typename Scope >
void tnl_indexing( Scope & scope )
{
using Index = typename Array::IndexType;
using Element = typename Array::ElementType;
scope.def("__len__", &Array::getSize);
scope.def("__iter__",
[]( Array& array ) {
return py::make_iterator(
RawIterator<Element>(array.getData()),
RawIterator<Element>(array.getData() + array.getSize()) );
},
py::keep_alive<0, 1>() // keep array alive while iterator is used
);
scope.def("__getitem__",
[](Array &a, Index i) {
if (i >= a.getSize())
throw py::index_error();
return a[i];
}
);
scope.def("__setitem__",
[](Array &a, Index i, const Element& e) {
if (i >= a.getSize())
throw py::index_error();
a[i] = e;
}
);
}
template< typename Array, typename Scope >
void tnl_slice_indexing( Scope & scope )
{
/// Slicing protocol
scope.def("__getitem__",
[](const Array& a, py::slice slice) -> Array* {
size_t start, stop, step, slicelength;
if (!slice.compute(a.getSize(), &start, &stop, &step, &slicelength))
throw py::error_already_set();
Array* seq = new Array();
seq->setSize(slicelength);
for (size_t i = 0; i < slicelength; ++i) {
seq->operator[](i) = a[start];
start += step;
}
return seq;
},
"Retrieve list elements using a slice object"
);
scope.def("__setitem__",
[](Array& a, py::slice slice, const Array& value) {
size_t start, stop, step, slicelength;
if (!slice.compute(a.getSize(), &start, &stop, &step, &slicelength))
throw py::error_already_set();
if (slicelength != (size_t) value.getSize())
throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
for (size_t i = 0; i < slicelength; ++i) {
a[start] = value[i];
start += step;
}
},
"Assign list elements using a slice object"
);
}