Author: Alex Gaynor <[email protected]>
Branch: numpy-dtype-alt
Changeset: r46866:c322561494f1
Date: 2011-08-28 14:41 -0400
http://bitbucket.org/pypy/pypy/changeset/c322561494f1/
Log: Fix for various arithmatic operations on bool arrays, including
their promotion to int8s in some circumstances. Also fixed
ll2ctypes turning lltype.Bool into a c_long, rather than a c_bool.
diff --git a/pypy/module/micronumpy/interp_dtype.py
b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -235,6 +235,9 @@
class IntegerArithmeticDtype(ArithmaticTypeMixin):
_mixin_ = True
+ def unwrap(self, space, w_item):
+ return self.adapt_val(space.int_w(space.int(w_item)))
+
def for_computation(self, v):
return widen(v)
@@ -262,7 +265,7 @@
T = lltype.Bool,
valtype = bool,
)
-class W_BoolDtype(W_BoolDtype):
+class W_BoolDtype(IntegerArithmeticDtype, W_BoolDtype):
def unwrap(self, space, w_item):
return self.adapt_val(space.is_true(w_item))
@@ -273,10 +276,6 @@
def for_computation(self, v):
return int(v)
- @binop
- def add(self, v1, v2):
- return bool(v1 + v2)
-
W_Int8Dtype = create_low_level_dtype(
num = 1, kind = SIGNEDLTR, name = "int8",
aliases = ["int8"],
@@ -296,8 +295,7 @@
valtype = rffi.INT._type,
)
class W_Int32Dtype(IntegerArithmeticDtype, W_Int32Dtype):
- def unwrap(self, space, w_item):
- return self.adapt_val(space.int_w(space.int(w_item)))
+ pass
W_Int64Dtype = create_low_level_dtype(
num = 9, kind = SIGNEDLTR, name = "int64",
@@ -307,8 +305,7 @@
valtype = rffi.LONGLONG._type,
)
class W_Int64Dtype(IntegerArithmeticDtype, W_Int64Dtype):
- def unwrap(self, space, w_item):
- return self.adapt_val(space.int_w(space.int(w_item)))
+ pass
W_Float64Dtype = create_low_level_dtype(
num = 12, kind = FLOATINGLTR, name = "float64",
diff --git a/pypy/module/micronumpy/interp_ufuncs.py
b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -2,9 +2,9 @@
from pypy.tool.sourcetools import func_with_new_name
-def ufunc(func=None, promote_to_float=False):
+def ufunc(func=None, promote_to_float=False, promote_bools=False):
if func is None:
- return lambda func: ufunc(func, promote_to_float)
+ return lambda func: ufunc(func, promote_to_float, promote_bools)
call_sig = signature.Call1(func)
def impl(space, w_obj):
from pypy.module.micronumpy.interp_numarray import (Call1,
@@ -14,6 +14,7 @@
res_dtype = find_unaryop_result_dtype(space,
w_obj.find_dtype(),
promote_to_float=promote_to_float,
+ promote_bools=promote_bools,
)
if isinstance(w_obj, Scalar):
return func(res_dtype,
w_obj.value.convert_to(res_dtype)).wrap(space)
@@ -24,9 +25,9 @@
return w_res
return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
-def ufunc2(func=None, promote_to_float=False):
+def ufunc2(func=None, promote_to_float=False, promote_bools=False):
if func is None:
- return lambda func: ufunc2(func, promote_to_float)
+ return lambda func: ufunc2(func, promote_to_float, promote_bools)
call_sig = signature.Call2(func)
def impl(space, w_lhs, w_rhs):
@@ -38,6 +39,7 @@
res_dtype = find_binop_result_dtype(space,
w_lhs.find_dtype(), w_rhs.find_dtype(),
promote_to_float=promote_to_float,
+ promote_bools=promote_bools,
)
if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
return func(res_dtype, w_lhs.value, w_rhs.value).wrap(space)
@@ -51,7 +53,8 @@
return w_res
return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
-def find_binop_result_dtype(space, dt1, dt2, promote_bools=False,
promote_to_float=False):
+def find_binop_result_dtype(space, dt1, dt2, promote_to_float=False,
+ promote_bools=False):
# dt1.num should be <= dt2.num
if dt1.num > dt2.num:
dt1, dt2 = dt2, dt1
@@ -71,7 +74,9 @@
assert False
def find_unaryop_result_dtype(space, dt, promote_to_float=False,
- promote_to_largest=False):
+ promote_to_largest=False, promote_bools=False):
+ if promote_bools and (dt.kind == interp_dtype.BOOLLTR):
+ return space.fromcache(interp_dtype.W_Int8Dtype)
if promote_to_float:
for bytes, dtype in interp_dtype.dtypes_by_num_bytes:
if dtype.kind == interp_dtype.FLOATINGLTR and dtype.num_bytes >=
dt.num_bytes:
@@ -116,9 +121,9 @@
("add", "add", 2),
("subtract", "sub", 2),
("multiply", "mul", 2),
- ("divide", "div", 2),
- ("mod", "mod", 2),
- ("power", "pow", 2),
+ ("divide", "div", 2, {"promote_bools": True}),
+ ("mod", "mod", 2, {"promote_bools": True}),
+ ("power", "pow", 2, {"promote_bools": True}),
("maximum", "max", 2),
("minimum", "min", 2),
@@ -128,7 +133,7 @@
("positive", "pos", 1),
("negative", "neg", 1),
("absolute", "abs", 1),
- ("sign", "sign", 1),
+ ("sign", "sign", 1, {"promote_bools": True}),
("reciprocal", "reciprocal", 1),
("fabs", "fabs", 1, {"promote_to_float": True}),
diff --git a/pypy/module/micronumpy/test/test_numarray.py
b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -236,12 +236,19 @@
assert b[i] == i - 5
def test_mul(self):
- from numpy import array
+ from numpy import array, dtype
a = array(range(5))
b = a * a
for i in range(5):
assert b[i] == i * i
+ a = array(range(5), dtype=bool)
+ b = a * a
+ assert b.dtype is dtype(bool)
+ assert b[0] is False
+ for i in range(1, 5):
+ assert b[i] is True
+
def test_mul_constant(self):
from numpy import array
a = array(range(5))
@@ -250,12 +257,18 @@
assert b[i] == i * 5
def test_div(self):
- from numpy import array
+ from numpy import array, dtype
a = array(range(1, 6))
b = a / a
for i in range(5):
assert b[i] == 1
+ a = array(range(1, 6), dtype=bool)
+ b = a / a
+ assert b.dtype is dtype("int8")
+ for i in range(5):
+ assert b[i] == 1
+
def test_div_other(self):
from numpy import array
a = array(range(5))
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py
b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -124,7 +124,7 @@
assert c[i] == a[i] * b[i]
def test_sign(self):
- from numpy import array, sign
+ from numpy import array, sign, dtype
reference = [-1.0, 0.0, 0.0, 1.0]
a = array([-5.0, -0.0, 0.0, 6.0])
@@ -137,6 +137,11 @@
for i in range(10):
assert a[i] == ref[i]
+ a = sign(array([True, False], dtype=bool))
+ assert a.dtype == dtype("int8")
+ assert a[0] == 1
+ assert a[1] == 0
+
def test_reciporocal(self):
from numpy import array, reciprocal
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py
b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -113,7 +113,7 @@
rffi.LONGLONG: ctypes.c_longlong,
rffi.ULONGLONG: ctypes.c_ulonglong,
rffi.SIZE_T: ctypes.c_size_t,
- lltype.Bool: ctypes.c_long, # XXX
+ lltype.Bool: ctypes.c_bool,
llmemory.Address: ctypes.c_void_p,
llmemory.GCREF: ctypes.c_void_p,
llmemory.WeakRef: ctypes.c_void_p, # XXX
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit