Author: Stefan H. Muller <[email protected]>
Branch: pypy-pyarray
Changeset: r66343:bb2aafab5a92
Date: 2013-08-08 00:41 +0200
http://bitbucket.org/pypy/pypy/changeset/bb2aafab5a92/

Log:    Add PyArray_New() and many macros for f2py.

        The modified version of f2py from the numpy pypy-hack branch
        generates code that compiles with this, but the generated modules
        don't work due to bypassing of Py_InitModule().

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -404,7 +404,7 @@
 
     'PyFunction_Type', 'PyMethod_Type', 'PyRange_Type', 'PyTraceBack_Type',
     
-    'PyArray_ZEROS',
+    'PyArray_Type', '_PyArray_FILLWBYTE', '_PyArray_ZEROS', 
'_PyArray_CopyInto',
 
     'Py_DebugFlag', 'Py_VerboseFlag', 'Py_InteractiveFlag', 'Py_InspectFlag',
     'Py_OptimizeFlag', 'Py_NoSiteFlag', 'Py_BytesWarningFlag', 
'Py_UseClassExceptionsFlag', 
diff --git a/pypy/module/cpyext/include/numpy/arrayobject.h 
b/pypy/module/cpyext/include/numpy/arrayobject.h
--- a/pypy/module/cpyext/include/numpy/arrayobject.h
+++ b/pypy/module/cpyext/include/numpy/arrayobject.h
@@ -13,13 +13,20 @@
 
 /* fake PyArrayObject so that code that doesn't do direct field access works */
 #define PyArrayObject PyObject
+#define PyArray_Descr PyObject
+
+PyTypeObject PyArray_Type;
 
 typedef unsigned char npy_bool;
 typedef unsigned char npy_uint8;
+typedef int npy_int;
 
 #ifndef npy_intp
 #define npy_intp long
 #endif
+#ifndef NPY_INTP_FMT
+#define NPY_INTP_FMT "ld"
+#endif
 #ifndef import_array
 #define import_array()
 #endif
@@ -73,21 +80,51 @@
 #define NPY_COMPLEX32 NPY_CFLOAT
 #define NPY_COMPLEX64 NPY_CDOUBLE
 
+#define PyTypeNum_ISBOOL(type)      ((type) == NPY_BOOL)
+#define PyTypeNum_ISINTEGER(type)  (((type) >= NPY_BYTE) && \
+                                    ((type) <= NPY_ULONGLONG))
+#define PyTypeNum_ISFLOAT(type)   ((((type) >= NPY_FLOAT) && \
+                                    ((type) <= NPY_LONGDOUBLE)) || \
+                                    ((type) == NPY_HALF))
+#define PyTypeNum_ISCOMPLEX(type)  (((type) >= NPY_CFLOAT) && \
+                                    ((type) <= NPY_CLONGDOUBLE))
+
+#define PyArray_ISBOOL(arr)    (PyTypeNum_ISBOOL(PyArray_TYPE(arr)))
+#define PyArray_ISINTEGER(arr) (PyTypeNum_ISINTEGER(PyArray_TYPE(arr)))
+#define PyArray_ISFLOAT(arr)   (PyTypeNum_ISFLOAT(PyArray_TYPE(arr)))
+#define PyArray_ISCOMPLEX(arr) (PyTypeNum_ISCOMPLEX(PyArray_TYPE(arr)))
+
 
 /* selection of flags */
-#define NPY_C_CONTIGUOUS    0x0001
+#define NPY_CONTIGUOUS      0x0001
+#define NPY_FORTRAN         0x0002
 #define NPY_OWNDATA         0x0004
+#define NPY_FORCECAST       0x0010
 #define NPY_ALIGNED         0x0100
-#define NPY_IN_ARRAY (NPY_C_CONTIGUOUS | NPY_ALIGNED)
-
+#define NPY_NOTSWAPPED      0x0200
+#define NPY_WRITEABLE       0x0400
+#define NPY_C_CONTIGUOUS    NPY_CONTIGUOUS
+#define NPY_F_CONTIGUOUS    NPY_FORTRAN
+#define NPY_IN_ARRAY       (NPY_C_CONTIGUOUS | NPY_ALIGNED)
+#define NPY_BEHAVED        (NPY_ALIGNED | NPY_WRITEABLE)
+#define NPY_CARRAY         (NPY_CONTIGUOUS | NPY_BEHAVED)
+#define NPY_FARRAY         (NPY_FORTRAN | NPY_BEHAVED)
+#define NPY_DEFAULT         NPY_CARRAY
 
 /* functions */
 #ifndef PyArray_NDIM
 
-#define PyArray_ISCONTIGUOUS(arr) (1)
-
 #define PyArray_Check      _PyArray_Check
 #define PyArray_CheckExact _PyArray_CheckExact
+
+#define PyArray_ISONESEGMENT(arr) (1)
+#define PyArray_FLAGS(arr)        (0)
+
+#define PyArray_ISCONTIGUOUS _PyArray_ISCONTIGUOUS
+
+#define PyArray_ISCARRAY(arr)   PyArray_ISCONTIGUOUS(arr)
+#define PyArray_ISFARRAY(arr) (!PyArray_ISCONTIGUOUS(arr))
+
 #define PyArray_NDIM       _PyArray_NDIM
 #define PyArray_DIM        _PyArray_DIM
 #define PyArray_STRIDE     _PyArray_STRIDE
@@ -106,8 +143,10 @@
 #define PyArray_ContiguousFromAny PyArray_FromObject
 
 #define PyArray_FROMANY(obj, typenum, min, max, requirements) (obj)
-#define PyArray_FROM_OTF(obj, typenum, requirements) (obj)
+#define PyArray_FROM_OTF(obj, typenum, requirements) \
+        PyArray_FromObject(obj, typenum, 0, 0)
 
+#define PyArray_New _PyArray_New
 #define PyArray_SimpleNew _PyArray_SimpleNew
 #define PyArray_SimpleNewFromData _PyArray_SimpleNewFromData
 #define PyArray_SimpleNewFromDataOwning _PyArray_SimpleNewFromDataOwning
@@ -115,7 +154,13 @@
 #define PyArray_EMPTY(nd, dims, type_num, fortran) \
         PyArray_SimpleNew(nd, dims, type_num)
 
-PyObject* PyArray_ZEROS(int nd, npy_intp* dims, int type_num, int fortran);
+void _PyArray_FILLWBYTE(PyObject* obj, int val);
+PyObject* _PyArray_ZEROS(int nd, npy_intp* dims, int type_num, int fortran);
+int _PyArray_CopyInto(PyArrayObject* dest, PyArrayObject* src);
+
+#define PyArray_FILLWBYTE _PyArray_FILLWBYTE
+#define PyArray_ZEROS _PyArray_ZEROS
+#define PyArray_CopyInto _PyArray_CopyInto
 
 #define PyArray_Resize(self, newshape, refcheck, fortran) (NULL)
 
diff --git a/pypy/module/cpyext/ndarrayobject.py 
b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -2,6 +2,7 @@
 Numpy C-API for PyPy - S. H. Muller, 2013/07/26
 """
 
+from pypy.interpreter.error import OperationError
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import cpython_api, Py_ssize_t, CANNOT_FAIL
 from pypy.module.cpyext.pyobject import PyObject
@@ -10,6 +11,9 @@
 from pypy.module.micronumpy.arrayimpl.scalar import Scalar
 from rpython.rlib.rawstorage import RAW_STORAGE_PTR
 
+NPY_FORTRAN = 0x0002
+NPY_OWNDATA = 0x0004
+
 # the asserts are needed, otherwise the translation fails
 
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
@@ -26,7 +30,13 @@
     return space.is_w(w_obj_type, w_type)
 
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def _PyArray_ISCONTIGUOUS(space, w_array):
+    assert isinstance(w_array, W_NDimArray)
+    return w_array.implementation.order == 'C'
+
+
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def _PyArray_NDIM(space, w_array):
     assert isinstance(w_array, W_NDimArray)
     return len(w_array.get_shape())
@@ -46,7 +56,7 @@
     assert isinstance(w_array, W_NDimArray)
     return w_array.get_size()
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def _PyArray_ITEMSIZE(space, w_array):
     assert isinstance(w_array, W_NDimArray)
     return w_array.get_dtype().get_size()
@@ -56,7 +66,7 @@
     assert isinstance(w_array, W_NDimArray)
     return w_array.get_size() * w_array.get_dtype().get_size()
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def _PyArray_TYPE(space, w_array):
     assert isinstance(w_array, W_NDimArray)
     return w_array.get_dtype().num
@@ -99,30 +109,34 @@
         return wrap_impl(space, space.type(w_array), w_array, new_impl)
 
 
-@cpython_api([Py_ssize_t, rffi.LONGP, Py_ssize_t], PyObject)
-def _PyArray_SimpleNew(space, nd, dims, typenum):
-    dtype = get_dtype_cache(space).dtypes_by_num[typenum]
+def get_shape_and_dtype(space, nd, dims, typenum):
     shape = []
     for i in range(nd):
         # back-and-forth wrapping needed to translate
         shape.append(space.int_w(space.wrap(dims[i])))
+    dtype = get_dtype_cache(space).dtypes_by_num[typenum]
+    return shape, dtype
 
+def simple_new(space, nd, dims, typenum,
+        order='C', owning=False, w_subtype=None):
+    shape, dtype = get_shape_and_dtype(space, nd, dims, typenum)
     return W_NDimArray.from_shape(space, shape, dtype)
 
-
-def simple_new_from_data(space, nd, dims, typenum, data, owning):
-    dtype = get_dtype_cache(space).dtypes_by_num[typenum]
+def simple_new_from_data(space, nd, dims, typenum, data, 
+        order='C', owning=False, w_subtype=None):
+    shape, dtype = get_shape_and_dtype(space, nd, dims, typenum)
     storage = rffi.cast(RAW_STORAGE_PTR, data)
     if nd == 0:
         w_val = dtype.itemtype.box_raw_data(storage)
         return W_NDimArray(Scalar(dtype, w_val))
-    else:
-        shape = []
-        for i in range(nd):
-            # back-and-forth wrapping needed to translate
-            shape.append(space.int_w(space.wrap(dims[i])))
-        
-        return W_NDimArray.from_shape_and_storage(space, shape, storage, 
dtype, owning=owning)
+    else:        
+        return W_NDimArray.from_shape_and_storage(space, shape, storage, 
dtype, 
+                order=order, owning=owning, w_subtype=w_subtype)
+
+
+@cpython_api([Py_ssize_t, rffi.LONGP, Py_ssize_t], PyObject)
+def _PyArray_SimpleNew(space, nd, dims, typenum):
+    return simple_new(space, nd, dims, typenum)
 
 @cpython_api([Py_ssize_t, rffi.LONGP, Py_ssize_t, rffi.VOIDP], PyObject)
 def _PyArray_SimpleNewFromData(space, nd, dims, typenum, data):
@@ -135,3 +149,24 @@
     #     ((PyArrayObject*)arr)->flags |= NPY_OWNDATA;
     return simple_new_from_data(space, nd, dims, typenum, data, owning=True)
 
+
+@cpython_api([rffi.VOIDP, Py_ssize_t, rffi.LONGP, Py_ssize_t, rffi.LONGP,
+    rffi.VOIDP, Py_ssize_t, Py_ssize_t, PyObject], PyObject)
+def _PyArray_New(space, subtype, nd, dims, typenum, strides, data, itemsize, 
flags, obj):
+    if strides:
+        raise OperationError(space.w_NotImplementedError, 
+                             space.wrap("strides must be NULL"))
+
+    order = 'F' if flags & NPY_FORTRAN else 'C'
+    owning = True if flags & NPY_OWNDATA else False
+    w_subtype = None
+
+    if data:
+        return simple_new_from_data(space, nd, dims, typenum, data, 
+            order=order, owning=owning, w_subtype=w_subtype)
+    else:
+        return simple_new(space, nd, dims, typenum,
+            order=order, owning=owning, w_subtype=w_subtype)
+
+
+
diff --git a/pypy/module/cpyext/src/ndarrayobject.c 
b/pypy/module/cpyext/src/ndarrayobject.c
--- a/pypy/module/cpyext/src/ndarrayobject.c
+++ b/pypy/module/cpyext/src/ndarrayobject.c
@@ -1,13 +1,27 @@
 
 #include "Python.h"
 #include "numpy/arrayobject.h"
-#include <string.h>   /* memset */
+#include <string.h>   /* memset, memcpy */
+
+PyTypeObject PyArray_Type;
+
+void 
+_PyArray_FILLWBYTE(PyObject* obj, int val) {
+    memset(PyArray_DATA(obj), val, PyArray_NBYTES(obj));
+}
 
 PyObject* 
-PyArray_ZEROS(int nd, npy_intp* dims, int type_num, int fortran) 
+_PyArray_ZEROS(int nd, npy_intp* dims, int type_num, int fortran) 
 {
     PyObject *arr = PyArray_EMPTY(nd, dims, type_num, fortran);
     memset(PyArray_DATA(arr), 0, PyArray_NBYTES(arr));
     return arr;
 }
 
+int 
+_PyArray_CopyInto(PyArrayObject* dest, PyArrayObject* src)
+{
+    memcpy(PyArray_DATA(dest), PyArray_DATA(src), PyArray_NBYTES(dest));
+    return 0;
+}
+
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py 
b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -11,13 +11,13 @@
     dtype = get_dtype_cache(space).w_float64dtype
     return W_NDimArray.new_scalar(space, dtype, space.wrap(10.))
 
-def array(space, shape):
+def array(space, shape, order='C'):
     dtype = get_dtype_cache(space).w_float64dtype
-    return W_NDimArray.from_shape(space, shape, dtype, order='C')
+    return W_NDimArray.from_shape(space, shape, dtype, order=order)
 
-def iarray(space, shape):
+def iarray(space, shape, order='C'):
     dtype = get_dtype_cache(space).w_int64dtype
-    return W_NDimArray.from_shape(space, shape, dtype, order='C')
+    return W_NDimArray.from_shape(space, shape, dtype, order=order)
 
 
 NULL = lltype.nullptr(rffi.VOIDP.TO)
@@ -32,6 +32,12 @@
         assert not api._PyArray_Check(x)
         assert not api._PyArray_CheckExact(x)
 
+    def test_ISCONTIGUOUS(self, space, api):
+        a = array(space, [10, 5, 3], order='C')
+        f = array(space, [10, 5, 3], order='F')
+        assert api._PyArray_ISCONTIGUOUS(a) == 1
+        assert api._PyArray_ISCONTIGUOUS(f) == 0
+        
     def test_NDIM(self, space, api):
         a = array(space, [10, 5, 3])
         assert api._PyArray_NDIM(a) == 3
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to