Skip to content

Prevent lossy conversions #1305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
davidhewitt opened this issue Feb 28, 2018 · 0 comments
Open

Prevent lossy conversions #1305

davidhewitt opened this issue Feb 28, 2018 · 0 comments

Comments

@davidhewitt
Copy link
Contributor

Issue description

Pybind11 by default permits lossy conversions from numpy arithmetic types to c++ ones.

I understand the reasoning behind the current situation: that python doesn't really have numeric types other than "float" and "long", and so conversion from python numeric types is always going to be potentially truncating.

However, for numpy scalars (int64, float64, etc.), there is a hierarchy of precision that has direct matches to c++ types. For the work I'm doing accidental loss of precision can be dangerous, so with the boost::python bindings we're looking to migrate away from we've gone to extensive trouble to avoid truncating casts of numpy values from python to c++.

I am aware that for py::array_t I can disable forcecasting (aside, I agree with the discussion in #338 that probably no forecasting is a better default).

However, for wrapped functions that take e.g. int32_t or std::vector<int32_t>, then truncation of numpy values can occur.

I think that making the type_caster for numeric types aware of numpy scalars would make it possible to prevent e.g. np.int64 successfully casting to int32_t.

Would such a change be possible? I think this has to be done within the pybind11 cast.h header itself.

With pybind11's first-class support for numpy this feels like it would be a great addition.

Thanks
David

Reproducible example code

For example, this binding code:

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
PYBIND11_MODULE(pybind_numpy, m)
{
  m.def (
    "test_takes_int32",
    [] (const int32_t i)
    {
      return i;
    });
  m.def (
    "test_takes_vec_int32",
    [] (const std::vector<int32_t> vec)
    {
      return vec;
    });
}

Can be called like so, but to avoid truncating conversions we would need both of these calls to be TypeErrors:

import pybind_numpy
import numpy as np

# scalar converting to lower-precision scalar
print(pybind_numpy.test_takes_int32(np.int64(1000)))  

# array is iterated by pybind11 and contained scalars being cast to lower-precision scalars
print(pybind_numpy.test_takes_vec_int32(np.array([1000, 2000], dtype=np.int64)))   
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

No branches or pull requests

1 participant