2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-27 07:02:15 +00:00

add more permissive equivalence test for dtypes, start using it in tests

This commit is contained in:
Jim Bosch
2012-09-18 23:13:29 -04:00
parent 46b959cceb
commit 2f7742ffec
4 changed files with 40 additions and 19 deletions

View File

@@ -43,6 +43,14 @@ public:
/// @brief Return the size of the data type in bytes.
int get_itemsize() const;
/**
* @brief Compare two dtypes for equivalence.
*
* This is more permissive than equality tests. For instance, if long and int are the same
* size, the dtypes corresponding to each will be equivalent, but not equal.
*/
friend bool equivalent(dtype const & a, dtype const & b);
/**
* @brief Register from-Python converters for NumPy's built-in array scalar types.
*
@@ -55,6 +63,8 @@ public:
};
bool equivalent(dtype const & a, dtype const & b);
namespace detail
{

View File

@@ -81,6 +81,13 @@ python::detail::new_reference dtype::convert(python::object const & arg, bool al
int dtype::get_itemsize() const { return reinterpret_cast<PyArray_Descr*>(ptr())->elsize;}
bool equivalent(dtype const & a, dtype const & b) {
return PyArray_EquivTypes(
reinterpret_cast<PyArray_Descr*>(a.ptr()),
reinterpret_cast<PyArray_Descr*>(b.ptr())
);
}
namespace {
namespace pyconv = boost::python::converter;

View File

@@ -6,46 +6,49 @@ import numpy
class DtypeTestCase(unittest.TestCase):
def assertEquivalent(self, a, b):
return self.assert_(dtype_mod.equivalent(a, b), "%r is not equivalent to %r")
def testIntegers(self):
for bits in (8, 16, 32, 64):
s = getattr(numpy, "int%d" % bits)
u = getattr(numpy, "uint%d" % bits)
fs = getattr(dtype_mod, "accept_int%d" % bits)
fu = getattr(dtype_mod, "accept_uint%d" % bits)
self.assertEqual(fs(s(1)), numpy.dtype(s))
self.assertEqual(fu(u(1)), numpy.dtype(u))
self.assertEquivalent(fs(s(1)), numpy.dtype(s))
self.assertEquivalent(fu(u(1)), numpy.dtype(u))
# these should just use the regular Boost.Python converters
self.assertEqual(fs(True), numpy.dtype(s))
self.assertEqual(fu(True), numpy.dtype(u))
self.assertEqual(fs(int(1)), numpy.dtype(s))
self.assertEqual(fu(int(1)), numpy.dtype(u))
self.assertEqual(fs(long(1)), numpy.dtype(s))
self.assertEqual(fu(long(1)), numpy.dtype(u))
self.assertEquivalent(fs(True), numpy.dtype(s))
self.assertEquivalent(fu(True), numpy.dtype(u))
self.assertEquivalent(fs(int(1)), numpy.dtype(s))
self.assertEquivalent(fu(int(1)), numpy.dtype(u))
self.assertEquivalent(fs(long(1)), numpy.dtype(s))
self.assertEquivalent(fu(long(1)), numpy.dtype(u))
for name in ("bool_", "byte", "ubyte", "short", "ushort", "intc", "uintc"):
t = getattr(numpy, name)
ft = getattr(dtype_mod, "accept_%s" % name)
self.assertEqual(ft(t(1)), numpy.dtype(t))
self.assertEquivalent(ft(t(1)), numpy.dtype(t))
# these should just use the regular Boost.Python converters
self.assertEqual(ft(True), numpy.dtype(t))
self.assertEquivalent(ft(True), numpy.dtype(t))
if name != "bool_":
self.assertEqual(ft(int(1)), numpy.dtype(t))
self.assertEqual(ft(long(1)), numpy.dtype(t))
self.assertEquivalent(ft(int(1)), numpy.dtype(t))
self.assertEquivalent(ft(long(1)), numpy.dtype(t))
def testFloats(self):
f = numpy.float32
c = numpy.complex64
self.assertEqual(dtype_mod.accept_float32(f(numpy.pi)), numpy.dtype(f))
self.assertEqual(dtype_mod.accept_complex64(c(1+2j)), numpy.dtype(c))
self.assertEquivalent(dtype_mod.accept_float32(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_mod.accept_complex64(c(1+2j)), numpy.dtype(c))
f = numpy.float64
c = numpy.complex128
self.assertEqual(dtype_mod.accept_float64(f(numpy.pi)), numpy.dtype(f))
self.assertEqual(dtype_mod.accept_complex128(c(1+2j)), numpy.dtype(c))
self.assertEquivalent(dtype_mod.accept_float64(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_mod.accept_complex128(c(1+2j)), numpy.dtype(c))
if hasattr(numpy, "longdouble"):
f = numpy.longdouble
c = numpy.clongdouble
self.assertEqual(dtype_mod.accept_longdouble(f(numpy.pi)), numpy.dtype(f))
self.assertEqual(dtype_mod.accept_clongdouble(c(1+2j)), numpy.dtype(c))
self.assertEquivalent(dtype_mod.accept_longdouble(f(numpy.pi)), numpy.dtype(f))
self.assertEquivalent(dtype_mod.accept_clongdouble(c(1+2j)), numpy.dtype(c))
if __name__=="__main__":

View File

@@ -9,10 +9,11 @@ np::dtype accept(T) {
return np::dtype::get_builtin<T>();
}
BOOST_PYTHON_MODULE(dtype_mod)
{
np::initialize();
// wrap dtype equivalence test, since it isn't available in Python API.
p::def("equivalent", np::equivalent);
// integers, by number of bits
p::def("accept_int8", accept<boost::int8_t>);
p::def("accept_uint8", accept<boost::uint8_t>);