[pypy-commit] pypy cpyext-injection: test one, add some tp_as_number methods

mattip pypy.commits at gmail.com
Wed Oct 26 16:37:47 EDT 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-injection
Changeset: r87954:ab7fe034304c
Date: 2016-10-26 23:36 +0300
http://bitbucket.org/pypy/pypy/changeset/ab7fe034304c/

Log:	test one, add some tp_as_number methods

diff --git a/pypy/module/cpyext/injection/test/multiarray.c b/pypy/module/cpyext/injection/test/multiarray.c
--- a/pypy/module/cpyext/injection/test/multiarray.c
+++ b/pypy/module/cpyext/injection/test/multiarray.c
@@ -1,4 +1,5 @@
 #include "Python.h"
+#include "pymath.h"
 
 typedef Py_intptr_t npy_intp;
 
@@ -275,6 +276,106 @@
     return NULL;
 }
 
+enum kOP {MULT, ADD, SUB, DIV};
+
+static PyObject*
+array_op(PyObject* obj1, PyObject* obj2, enum kOP op)
+{
+    int n1=-1, n2=-1, m, i1, i2, j;
+    double *v1, *v2, *r, tmp1, tmp2;
+    PyObject* ret = NULL, *tuple=NULL;
+    if (obj1->ob_type == &PyArray_Type)
+    {
+        n1 = ((PyArrayObject*)obj1)->dimensions[0];
+        v1 = (double*)((PyArrayObject*)obj1)->data;       
+    }
+    else
+    {
+        tmp1 = PyFloat_AsDouble(obj1);
+        if (PyErr_Occurred())
+            return NULL;
+        v1 = &tmp1;
+    }
+    if (obj2->ob_type == &PyArray_Type)
+    {
+        n2 = ((PyArrayObject*)obj2)->dimensions[0];
+        v2 = (double*)((PyArrayObject*)obj2)->data;       
+    }
+    else
+    {
+        tmp2 = PyFloat_AsDouble(obj2);
+        if (PyErr_Occurred())
+            return NULL;
+        v2 = &tmp2;
+    }
+    if (!(n1 == n2 || n1 == 1 || n2 == 1))
+    {
+        PyErr_SetString(PyExc_ValueError, "dimension mismatch");
+        return NULL;
+    }
+    m = n1 > n2? n1 : n2;
+    tuple = PyTuple_New(1);
+    PyTuple_SetItem(tuple, 0, PyInt_FromLong(m));
+    ret = array_new(&PyArray_Type, tuple, NULL);
+    Py_DECREF(tuple);
+    r = (double*)((PyArrayObject*)ret)->data;
+    for (i1=0, i2=0, j=0; j < m; j++, i1++, i2++)
+    {
+        if (i1 >= n1) i1 = 0;
+        if (i2 >= n2) i2 = 0;
+        switch (op)
+        {
+            case MULT:
+                r[j] = v1[i1] * v2[i2];
+                break;
+            case ADD:
+                r[j] = v1[i1] + v2[i2];
+                break;
+            case SUB:
+                r[j] = v1[i1] - v2[i2];
+                break;
+            case DIV:
+                if (v2[i2] == 0)
+                    r[j] = Py_NAN;
+                else
+                    r[j] = v1[i1] / v2[i2];
+                break;
+        }
+    } 
+    return ret;
+}
+
+static PyObject*
+array_multiply(PyObject* obj1, PyObject* obj2)
+{
+    return array_op(obj1, obj2, MULT);
+}
+
+static PyObject*
+array_add(PyObject* obj1, PyObject* obj2)
+{
+    return array_op(obj1, obj2, ADD);
+}
+
+static PyObject*
+array_sub(PyObject* obj1, PyObject* obj2)
+{
+    return array_op(obj1, obj2, SUB);
+}
+
+static PyObject*
+array_divide(PyObject* obj1, PyObject* obj2)
+{
+    return array_op(obj1, obj2, DIV);
+}
+
+static PyNumberMethods array_as_number = {
+    (binaryfunc)array_add, /* nb_add*/
+    (binaryfunc)array_sub, /* nb_subtract */
+    (binaryfunc)array_multiply, /* nb_multiply */
+    (binaryfunc)array_divide, /* nb_divide */
+};
+
 /* List of functions exported by this module */
 
 static PyMethodDef multiarray_functions[] = {
@@ -330,6 +431,8 @@
     if (module == NULL)
         INITERROR;
 
+    PyArray_Type.tp_as_number = &array_as_number;
+    
     if (PyType_Ready(&PyArray_Type) < 0)
         INITERROR;
     PyModule_AddObject(module, "ndarray", (PyObject *)&PyArray_Type);
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
@@ -36,3 +36,12 @@
         x = X(1)
         assert isinstance(x, X)
         assert isinstance(x, np.ndarray)
+
+    def test_plain_op(self):
+        np = self.import_module(name='numpy.core.multiarray_PLAIN',
+                                filename='../injection/test/multiarray')
+        a = np.ndarray(100);
+        for i in range(100):
+            a[i] = i
+        b = a * a
+        assert b[10] == 100.0 + 42.0


More information about the pypy-commit mailing list