[pypy-commit] pypy cpyext-injection: add injected vector ops (more tests needed)
mattip
pypy.commits at gmail.com
Thu Oct 27 13:16:25 EDT 2016
Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-injection
Changeset: r87961:6821c86e1e37
Date: 2016-10-27 20:14 +0300
http://bitbucket.org/pypy/pypy/changeset/6821c86e1e37/
Log: add injected vector ops (more tests needed)
diff --git a/pypy/module/cpyext/injection/numpy.py b/pypy/module/cpyext/injection/numpy.py
--- a/pypy/module/cpyext/injection/numpy.py
+++ b/pypy/module/cpyext/injection/numpy.py
@@ -20,6 +20,8 @@
("strides", rffi.SIGNEDP),
("base", rffi.VOIDP),
("descr", rffi.VOIDP),
+ ("flags", rffi.INT),
+ ("weakreflist", PyObject),
)))
)
@@ -64,14 +66,72 @@
data = rffi.cast(rffi.DOUBLEP, py_obj.data)
return W_Float64Object(data[index])
+def injected_op(space, w_self, w_other, op):
+ # translate array_op in multiarray.c from c to rpython
+ if isinstance(w_self, W_ArrayObject):
+ arr1 = rffi.cast(PyArrayObject, w_self.pyobj)
+ data1 = rffi.cast(rffi.DOUBLEP, arr1.data)
+ n1 = arr1.dimensions[0]
+ else:
+ data1 = [space.float_w(w_self),]
+ n1 = 1
+ if isinstance(w_other, W_ArrayObject):
+ arr2 = rffi.cast(PyArrayObject, w_self.pyobj)
+ data2 = rffi.cast(rffi.DOUBLEP, arr2.data)
+ n2 = arr2.dimensions[0]
+ else:
+ data2 = [space.int_w(w_other),]
+ n2 = 1
+ if not (n1 == n2 or n1 == 1 or n2 == 1):
+ raise oefmt(space.w_ValueError, 'dimension mismatch')
+ m = max(n1, n2)
+ org = space.fromcache(Original)
+ ret = space.call(org.w_array_type, space.newtuple([space.newint(m)]))
+ assert isinstance(ret, W_ArrayObject)
+ r = rffi.cast(rffi.DOUBLEP, ret.pyobj.data)
+ i1 = 0; i2 = 0
+ for j in range(m):
+ if i1 > n1: i1 = 0
+ if i2 > n2: i2 = 0
+ if op == 'mul':
+ r[j] = data1[i1] * data2[i2]
+ elif op == 'add':
+ r[j] = data1[i1] + data2[i2]
+ elif op == 'sub':
+ r[j] = data1[i1] - data2[i2]
+ elif op == 'div':
+ if data2[i2] == 0:
+ r[j] = float('nan')
+ else:
+ r[j] = data1[i1] / data2[i2]
+ i1 += 1; i2 += 1
+ return ret
+
+def injected_mul(space, w_self, w_other):
+ return injected_op(space, w_self, w_other, 'mul')
+
+def injected_add(space, w_self, w_other):
+ return injected_op(space, w_self, w_other, 'add')
+
+def injected_sub(space, w_self, w_other):
+ return injected_op(space, w_self, w_other, 'sub')
+
+def injected_div(space, w_self, w_other):
+ return injected_op(space, w_self, w_other, 'div')
+
injected_methods = {
'__getitem__': interp2app(injected_getitem),
+ '__mul__': interp2app(injected_mul),
+ '__add__': interp2app(injected_add),
+ '__sub__': interp2app(injected_sub),
+ '__div__': interp2app(injected_div),
}
def inject_operator(space, name, dict_w, pto):
assert name == 'numpy.ndarray'
org = space.fromcache(Original)
org.w_original_getitem = dict_w['__getitem__']
+ org.w_original_getitem = dict_w['__mul__']
for key, w_value in org.injected_methods_w:
dict_w[key] = w_value
return W_ArrayObject.typedef
diff --git a/pypy/module/cpyext/injection/test/test_numpy.py b/pypy/module/cpyext/injection/test/test_numpy.py
--- a/pypy/module/cpyext/injection/test/test_numpy.py
+++ b/pypy/module/cpyext/injection/test/test_numpy.py
@@ -45,3 +45,12 @@
a[i] = i
b = a * a
assert b[10] == 100.0 + 42.0
+
+ def test_injected_op(self):
+ np = self.import_module(name='numpy.core.multiarray',
+ filename='../injection/test/multiarray')
+ a = np.ndarray(100);
+ for i in range(100):
+ a[i] = i
+ b = a * a
+ assert b[10] == 100.0
More information about the pypy-commit
mailing list