Skip to content

Conversation

@jagerman
Copy link
Member

A few small-ish changes related to numpy:

  • the dtype declaration macro documentation was unclear
  • non-POD types resulted in non-obvious compilation errors (changed to a static_assert)
  • added long double (and std::complex<long double>) support: there's not a huge reason to not support them--supporting all floating point types makes the code a little cleaner--and this allows binding of Eigen code that has long doubles.

The changes to the numpy dtype test script also resolve the linux/i386 test failure from #612.

The current documentation and example reads as though
PYBIND11_NUMPY_DTYPE is a declarative macro along the same lines as
PYBIND11_DECLARE_HOLDER_TYPE, but it isn't.  The changes the
documentation and docs example to make it clear that you need to "call"
the macro.
@aldanor
Copy link
Member

aldanor commented Jan 26, 2017

Looks all good to me. Just wondering, why the = to ^ change for unaligned fields?

@jagerman
Copy link
Member Author

Two reasons: first ^ is basically the unaligned version of the default @, but more importantly, ^ lets the numpy-specific g, F, D, and G through. (Without it, g isn't supported at all, and the capital complex ones need to be Zf, Zd).

@aldanor
Copy link
Member

aldanor commented Jan 26, 2017

Oh, I see, good then. Can't remember to have encountered ^ in format strings myself, but it looks like that's the proper choice here.

Copy link
Member

@dean0x7d dean0x7d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the "Prefix macros with PYBIND11_" commit got accidentally reverted along the way. Specifically, DECL_NPY_API.


template <class T, template<class> class... Predicates> using is_all_of = all_of<Predicates<T>...>;
template <class T, template<class> class... Predicates> using is_any_of = any_of<Predicates<T>...>;
template <class T, template<class> class... Predicates> using is_none_of = none_of<Predicates<T>...>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having all_of and is_all_of might be a little confusing. Maybe satisfies_all_of?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good suggestion.


template <typename T> using is_pod_struct = all_of<
std::is_pod<T>, // offsetof only works correctly for POD types
is_none_of<T, std::is_reference, std::is_array, is_std_array, std::is_arithmetic, is_complex, std::is_enum>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is specifically std::array disallowed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it was before. (I didn't change the logic here, just cleaned it up a bit with convenience meta-templates). I seem to recall some discussion about coming back to handle that eventually (cc @aldanor?) at some point post 2.0.

template <typename T> struct is_complex<std::complex<T>> : std::true_type { };

template <typename T> using is_pod_struct = all_of<
std::is_pod<T>, // offsetof only works correctly for POD types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking: offsetof only needs is_standard_layout, it's numpy that needs the rest of is_pod.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copied the comment, but I'll update it.

`satisfies_all_of<T, Pred1, Pred2, Pred3>` is a nice legibility-enhanced
shortcut for `is_all<Pred1<T>, Pred2<T>, Pred3<T>>`.
If you try to use a non-POD data type, you get difficult-to-interpret
compilation errors (about ::name() not being a member of an internal
pybind11 struct, among others), for which isn't at all obvious what the
problem is.

This adds a static_assert for such cases.

It also changes the base case from an empty struct to the is_pod_struct
case by no longer using `enable_if<is_pod_struct>` but instead using a
static_assert: thus specializations avoid the base class, POD types
work, and non-POD types (and unimplemented POD types like std::array)
get a more informative static_assert failure.
numpy.h uses unprefixed macros, which seems undesirable.  This prefixes
them with PYBIND11_ to match all the other macros in numpy.h (and
elsewhere).
@jagerman
Copy link
Member Author

Not sure how I accidentally undid the DECL_NPY_API ones, but I fixed that too (and squashed everything).

@jagerman jagerman mentioned this pull request Jan 27, 2017
This adds long double and std::complex<long double> support for numpy
arrays.

This allows some simplification of the code used to generate format
descriptors; the new code uses fewer macros, instead putting the code as
different templated options; the template conditions end up simpler with
this because we are now supporting all basic C++ arithmetic types (and
so can use is_arithmetic instead of is_integral + multiple
different specializations).

In addition to testing that it is indeed working in the test script, it
also adds various offset and size calculations there, which
fixes the test failures under x86 compilations.
@wjakob
Copy link
Member

wjakob commented Jan 31, 2017

Looks all good, thank you!

@wjakob wjakob merged commit f7f5bc8 into pybind:master Jan 31, 2017
@jagerman jagerman modified the milestone: v2.1 Mar 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants