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