14 #define PYBIND11_PACKED(cls) cls __attribute__((__packed__))
16 #define PYBIND11_PACKED(cls) __pragma(pack(push, 1)) cls __pragma(pack(pop))
46 std::ostream&
operator<<(std::ostream& os,
const PackedStruct& v) {
47 return os <<
"p:" << v.bool_ <<
"," << v.uint_ <<
"," << v.float_ <<
"," << v.ldbl_;
55 std::ostream&
operator<<(std::ostream& os,
const NestedStruct& v) {
56 return os <<
"n:a=" << v.a <<
";b=" << v.b;
77 std::array<char, 3>
b;
86 return os <<
"c:" << v.
cflt <<
"," << v.
cdbl;
92 std::array<uint8_t, 3>
c;
93 std::array<float, 2>
d[4];
101 enum class E1 : int64_t {
A = -1,
B = 1 };
102 enum E2 : uint8_t {
X = 1,
Y = 2 };
111 for (
size_t i = 0;
i < 3 && v.
a[
i];
i++) os << v.
a[
i];
113 for (
size_t i = 0;
i < 3 && v.
b[
i];
i++) os << v.
b[
i];
119 for (
int i = 0;
i < 3;
i++) {
123 for (
int j = 0; j < 3; j++)
124 os << v.
a[
i][j] <<
',';
125 os << v.
a[
i][3] <<
'}';
127 os <<
"},b={" << v.
b[0] <<
',' << v.
b[1];
128 os <<
"},c={" << int(v.
c[0]) <<
',' << int(v.
c[1]) <<
',' << int(v.
c[2]);
130 for (
int i = 0;
i < 4;
i++) {
133 os <<
'{' << v.
d[
i][0] <<
',' << v.
d[
i][1] <<
'}';
138 std::ostream&
operator<<(std::ostream& os,
const EnumStruct& v) {
139 return os <<
"e1=" << (v.e1 == E1::A ?
"A" :
"B") <<
",e2=" << (v.e2 ==
E2::X ?
"X" :
"Y");
142 template <
typename T>
144 return py::array(py::buffer_info(
nullptr,
sizeof(T),
145 py::format_descriptor<T>::format(),
146 1, { n }, {
sizeof(T) }));
149 #define SET_TEST_VALS(s, i) do { \
150 s.bool_ = (i) % 2 != 0; \
151 s.uint_ = (uint32_t) (i); \
152 s.float_ = (float) (i) * 1.5f; \
153 s.ldbl_ = (long double) (i) * -2.5L; } while (0)
155 template <
typename S>
157 auto arr = mkarray_via_buffer<S>(n);
158 auto req =
arr.request();
159 auto ptr =
static_cast<S*
>(req.ptr);
160 for (
size_t i = 0;
i < n;
i++) {
166 template <
typename S>
168 const auto req =
arr.request();
169 const auto ptr =
static_cast<S*
>(req.ptr);
172 std::stringstream ss;
174 l.append(py::str(ss.str()));
180 using arr_t = py::array_t<int32_t, 0>;
182 std::vector<int32_t>
data { 1, 2, 3, 4, 5, 6 };
183 std::vector<py::ssize_t> shape { 3, 2 };
184 std::vector<py::ssize_t> strides { 8, 4 };
186 auto ptr =
data.data();
187 auto vptr = (
void *) ptr;
188 auto dtype = py::dtype(
"int32");
190 py::buffer_info buf_ndim1(vptr, 4,
"i", 6);
191 py::buffer_info buf_ndim1_null(
nullptr, 4,
"i", 6);
192 py::buffer_info buf_ndim2(vptr, 4,
"i", 2, shape, strides);
193 py::buffer_info buf_ndim2_null(
nullptr, 4,
"i", 2, shape, strides);
195 auto fill = [](py::array
arr) {
196 auto req =
arr.request();
197 for (
int i = 0;
i < 6;
i++) ((int32_t *) req.ptr)[
i] =
i + 1;
203 case 10:
return arr_t(shape, strides, ptr);
204 case 11:
return py::array(shape, strides, ptr);
205 case 12:
return py::array(
dtype, shape, strides, vptr);
206 case 13:
return arr_t(shape, ptr);
207 case 14:
return py::array(shape, ptr);
208 case 15:
return py::array(
dtype, shape, vptr);
209 case 16:
return arr_t(buf_ndim2);
210 case 17:
return py::array(buf_ndim2);
212 case 20:
return fill(
arr_t(shape, strides));
213 case 21:
return py::array(shape, strides, ptr);
214 case 22:
return fill(py::array(
dtype, shape, strides));
215 case 23:
return fill(
arr_t(shape));
216 case 24:
return py::array(shape, ptr);
217 case 25:
return fill(py::array(
dtype, shape));
218 case 26:
return fill(
arr_t(buf_ndim2_null));
219 case 27:
return fill(py::array(buf_ndim2_null));
221 case 30:
return arr_t(6, ptr);
222 case 31:
return py::array(6, ptr);
223 case 32:
return py::array(
dtype, 6, vptr);
224 case 33:
return arr_t(buf_ndim1);
225 case 34:
return py::array(buf_ndim1);
227 case 40:
return fill(
arr_t(6));
228 case 41:
return py::array(6, ptr);
229 case 42:
return fill(py::array(
dtype, 6));
230 case 43:
return fill(
arr_t(buf_ndim1_null));
231 case 44:
return fill(py::array(buf_ndim1_null));
239 list.
append(py::dtype(std::string(
"float64")));
240 list.
append(py::dtype::from_args(py::str(
"bool")));
241 py::list names, offsets, formats;
243 names.append(py::str(
"a")); names.append(py::str(
"b"));
dict[
"names"] = names;
244 offsets.append(py::int_(1)); offsets.append(py::int_(10));
dict[
"offsets"] = offsets;
245 formats.append(py::dtype(
"int32")); formats.append(py::dtype(
"float64"));
dict[
"formats"] = formats;
246 dict[
"itemsize"] = py::int_(20);
248 list.
append(py::dtype(names, formats, offsets, 20));
249 list.
append(py::dtype(py::buffer_info((
void *) 0,
sizeof(
unsigned int),
"I", 1)));
250 list.
append(py::dtype(py::buffer_info((
void *) 0, 0,
"T{i:a:f:b:}", 1)));
258 try { py::module_::import(
"numpy"); }
259 catch (...) {
return; }
262 py::class_<SimpleStruct>(
m,
"SimpleStruct")
272 .def_static(
"fromtuple", [](
const py::tuple tup) {
274 throw py::cast_error(
"Invalid size");
278 tup[1].cast<uint32_t>(),
279 tup[2].cast<
float>(),
280 tup[3].cast<long double>()};
295 py::class_<PackedStruct>(
m,
"PackedStruct");
306 py::detail::npy_format_descriptor<A>::register_dtype(
309 py::detail::npy_format_descriptor<B>::register_dtype(
310 std::vector<py::detail::field_descriptor>{}
314 m.def(
"create_rec_simple", &create_recarray<SimpleStruct>);
315 m.def(
"create_rec_packed", &create_recarray<PackedStruct>);
316 m.def(
"create_rec_nested", [](
size_t n) {
317 py::array_t<NestedStruct, 0>
arr = mkarray_via_buffer<NestedStruct>(n);
318 auto req =
arr.request();
319 auto ptr =
static_cast<NestedStruct*
>(req.ptr);
320 for (
size_t i = 0;
i < n;
i++) {
326 m.def(
"create_rec_partial", &create_recarray<PartialStruct>);
327 m.def(
"create_rec_partial_nested", [](
size_t n) {
328 py::array_t<PartialNestedStruct, 0>
arr = mkarray_via_buffer<PartialNestedStruct>(n);
329 auto req =
arr.request();
331 for (
size_t i = 0;
i < n;
i++) {
336 m.def(
"print_rec_simple", &print_recarray<SimpleStruct>);
337 m.def(
"print_rec_packed", &print_recarray<PackedStruct>);
338 m.def(
"print_rec_nested", &print_recarray<NestedStruct>);
341 m.def(
"get_format_unbound", []() {
return py::format_descriptor<UnboundStruct>::format(); });
342 m.def(
"print_format_descriptors", []() {
344 for (
const auto &fmt : {
345 py::format_descriptor<SimpleStruct>::format(),
346 py::format_descriptor<PackedStruct>::format(),
347 py::format_descriptor<NestedStruct>::format(),
348 py::format_descriptor<PartialStruct>::format(),
349 py::format_descriptor<PartialNestedStruct>::format(),
350 py::format_descriptor<StringStruct>::format(),
351 py::format_descriptor<ArrayStruct>::format(),
352 py::format_descriptor<EnumStruct>::format(),
353 py::format_descriptor<ComplexStruct>::format()
361 m.def(
"print_dtypes", []() {
363 for (
const py::handle &d : {
364 py::dtype::of<SimpleStruct>(),
365 py::dtype::of<PackedStruct>(),
366 py::dtype::of<NestedStruct>(),
367 py::dtype::of<PartialStruct>(),
368 py::dtype::of<PartialNestedStruct>(),
369 py::dtype::of<StringStruct>(),
370 py::dtype::of<ArrayStruct>(),
371 py::dtype::of<EnumStruct>(),
372 py::dtype::of<StructWithUglyNames>(),
373 py::dtype::of<ComplexStruct>()
375 l.append(py::str(d));
379 m.def(
"test_dtype_methods", []() {
381 auto dt1 = py::dtype::of<int32_t>();
382 auto dt2 = py::dtype::of<SimpleStruct>();
388 struct TrailingPaddingStruct {
393 m.def(
"trailing_padding_dtype", []() {
return py::dtype::of<TrailingPaddingStruct>(); });
396 m.def(
"create_string_array", [](
bool non_empty) {
397 py::array_t<StringStruct, 0>
arr = mkarray_via_buffer<StringStruct>(non_empty ? 4 : 0);
399 auto req =
arr.request();
402 static_cast<char*
>(req.ptr)[
i] = 0;
403 ptr[1].
a[0] =
'a'; ptr[1].b[0] =
'a';
404 ptr[2].a[0] =
'a'; ptr[2].b[0] =
'a';
405 ptr[3].a[0] =
'a'; ptr[3].b[0] =
'a';
407 ptr[2].a[1] =
'b'; ptr[2].b[1] =
'b';
408 ptr[3].a[1] =
'b'; ptr[3].b[1] =
'b';
410 ptr[3].a[2] =
'c'; ptr[3].b[2] =
'c';
414 m.def(
"print_string_array", &print_recarray<StringStruct>);
417 m.def(
"create_array_array", [](
size_t n) {
418 py::array_t<ArrayStruct, 0>
arr = mkarray_via_buffer<ArrayStruct>(n);
420 for (
size_t i = 0;
i < n;
i++) {
421 for (
size_t j = 0; j < 3; j++)
422 for (
size_t k = 0; k < 4; k++)
423 ptr[
i].a[j][k] =
char(
'A' + (
i * 100 + j * 10 + k) % 26);
424 for (
size_t j = 0; j < 2; j++)
425 ptr[
i].b[j] = int32_t(
i * 1000 + j);
426 for (
size_t j = 0; j < 3; j++)
427 ptr[
i].c[j] = uint8_t(
i * 10 + j);
428 for (
size_t j = 0; j < 4; j++)
429 for (
size_t k = 0; k < 2; k++)
430 ptr[
i].d[j][k] =
float(
i) * 100.0f + float(j) * 10.0f + float(k);
434 m.def(
"print_array_array", &print_recarray<ArrayStruct>);
437 m.def(
"create_enum_array", [](
size_t n) {
438 py::array_t<EnumStruct, 0>
arr = mkarray_via_buffer<EnumStruct>(n);
439 auto ptr = (EnumStruct *)
arr.mutable_data();
440 for (
size_t i = 0;
i < n;
i++) {
441 ptr[
i].e1 =
static_cast<E1>(-1 + ((int)
i % 2) * 2);
442 ptr[
i].e2 =
static_cast<E2>(1 + (
i % 2));
446 m.def(
"print_enum_array", &print_recarray<EnumStruct>);
449 m.def(
"create_complex_array", [](
size_t n) {
450 py::array_t<ComplexStruct, 0>
arr = mkarray_via_buffer<ComplexStruct>(n);
452 for (
size_t i = 0;
i < n;
i++) {
453 ptr[
i].cflt.real(
float(
i));
454 ptr[
i].cflt.imag(
float(
i) + 0.25f);
455 ptr[
i].cdbl.real(
double(
i) + 0.5);
456 ptr[
i].cdbl.imag(
double(
i) + 0.75);
460 m.def(
"print_complex_array", &print_recarray<ComplexStruct>);
466 struct CompareStruct {
472 m.def(
"compare_buffer_info", []() {
474 list.
append(py::bool_(py::detail::compare_buffer_info<float>::compare(py::buffer_info(
nullptr,
sizeof(
float),
"f", 1))));
475 list.
append(py::bool_(py::detail::compare_buffer_info<unsigned>::compare(py::buffer_info(
nullptr,
sizeof(
int),
"I", 1))));
476 list.
append(py::bool_(py::detail::compare_buffer_info<long>::compare(py::buffer_info(
nullptr,
sizeof(
long),
"l", 1))));
477 list.
append(py::bool_(py::detail::compare_buffer_info<long>::compare(py::buffer_info(
nullptr,
sizeof(
long),
sizeof(
long) ==
sizeof(
int) ?
"i" :
"q", 1))));
478 list.
append(py::bool_(py::detail::compare_buffer_info<CompareStruct>::compare(py::buffer_info(
nullptr,
sizeof(CompareStruct),
"T{?:x:3xI:y:f:z:}", 1))));
481 m.def(
"buffer_to_dtype", [](py::buffer& buf) {
return py::dtype(buf.request()); });
484 auto f_simple = [](
SimpleStruct s) {
return s.uint_ * 10; };
485 m.def(
"f_simple", f_simple);
486 m.def(
"f_packed", [](PackedStruct s) {
return s.uint_ * 10; });
487 m.def(
"f_nested", [](NestedStruct s) {
return s.a.uint_ * 10; });
491 auto f_simple_pass_thru = [](
SimpleStruct s) {
return s; };
492 m.def(
"f_simple_pass_thru_vectorized",
py::vectorize(f_simple_pass_thru));
498 m.def(
"dtype_wrapper", [](py::object d) {
return py::dtype::from_args(
std::move(d)); });