Commits

mattip  committed a029cfc Merge

merge pypy-pyarray which implements much of numpy's c api to access ndarray from c and also array.nozero

  • Participants
  • Parent commits aa4e8c5, a7a9634

Comments (0)

Files changed (48)

File lib_pypy/numpy.py

-raise ImportError(
-    "The 'numpy' module of PyPy is in-development and not complete. "
-    "To try it out anyway, you can either import from 'numpypy', "
-    "or just write 'import numpypy' first in your program and then "
-    "import from 'numpy' as usual.")
+import warnings
+import sys
+if 'numpypy' not in sys.modules:
+    warnings.warn(
+        "The 'numpy' module of PyPy is in-development and not complete. "
+        "To avoid this warning, write 'import numpypy as numpy'. ",
+        UserWarning) # XXX is this the best warning type?
+
+from numpypy import *
+import numpypy
+__all__ = numpypy.__all__
+del numpypy

File lib_pypy/numpypy/__init__.py

 from __builtin__ import bool, int, long, float, complex, object, unicode, str
 from core import abs, max, min
 
-__all__ = []
+__version__ = '1.7.0'
+
+import os
+def get_include():
+    head, tail = os.path.split(os.path.dirname(os.path.abspath(__file__)))
+    return os.path.join(head, '../include')
+
+
+__all__ = ['__version__', 'get_include']
 __all__ += core.__all__
 __all__ += lib.__all__
 
-import sys
-sys.modules.setdefault('numpy', sys.modules['numpypy'])
+#import sys
+#sys.modules.setdefault('numpy', sys.modules['numpypy'])
+
+

File lib_pypy/numpypy/core/fromnumeric.py

     (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
 
     """
-    raise NotImplementedError('Waiting on interp level method')
+    try:
+        nonzero = a.nonzero
+    except AttributeError:
+        res = _wrapit(a, 'nonzero')
+    else:
+        res = nonzero()
+    return res
 
 
 def shape(a):

File pypy/doc/whatsnew-head.rst

 .. branch: ndarray-subtype
 Allow subclassing ndarray, i.e. matrix
 
+.. branch: pypy-pyarray
+Implement much of numpy's c api in cpyext, allows (slow) access to ndarray
+from c
+
 .. branch: kill-ootype
 
 .. branch: fast-slowpath

File pypy/module/cpyext/__init__.py

 import pypy.module.cpyext.object
 import pypy.module.cpyext.stringobject
 import pypy.module.cpyext.tupleobject
+import pypy.module.cpyext.ndarrayobject
 import pypy.module.cpyext.setobject
 import pypy.module.cpyext.dictobject
 import pypy.module.cpyext.intobject

File pypy/module/cpyext/api.py

 udir.join('pypy_macros.h').write("/* Will be filled later */\n")
 globals().update(rffi_platform.configure(CConfig_constants))
 
-def copy_header_files(dstdir):
-    assert dstdir.check(dir=True)
-    headers = include_dir.listdir('*.h') + include_dir.listdir('*.inl')
-    for name in ("pypy_decl.h", "pypy_macros.h"):
-        headers.append(udir.join(name))
+def _copy_header_files(headers, dstdir):
     for header in headers:
         target = dstdir.join(header.basename)
         try:
         target.chmod(0444) # make the file read-only, to make sure that nobody
                            # edits it by mistake
 
+def copy_header_files(dstdir):
+    # XXX: 20 lines of code to recursively copy a directory, really??
+    assert dstdir.check(dir=True)
+    headers = include_dir.listdir('*.h') + include_dir.listdir('*.inl')
+    for name in ("pypy_decl.h", "pypy_macros.h"):
+        headers.append(udir.join(name))
+    _copy_header_files(headers, dstdir)
+
+    try:
+        dstdir.mkdir('numpy')
+    except py.error.EEXIST:
+        pass
+    numpy_dstdir = dstdir / 'numpy'
+
+    numpy_include_dir = include_dir / 'numpy'
+    numpy_headers = numpy_include_dir.listdir('*.h') + numpy_include_dir.listdir('*.inl')
+    _copy_header_files(numpy_headers, numpy_dstdir)
+
+
 class NotSpecified(object):
     pass
 _NOT_SPECIFIED = NotSpecified()
                         elif isinstance(input_arg, W_Root):
                             arg = input_arg
                         else:
-                            arg = from_ref(space,
+                            try:
+                                arg = from_ref(space,
                                            rffi.cast(PyObject, input_arg))
+                            except TypeError, e:
+                                err = OperationError(space.w_TypeError,
+                                         space.wrap(
+                                        "could not cast arg to PyObject"))
+                                if not catch_exception:
+                                    raise err
+                                state = space.fromcache(State)
+                                state.set_exception(err)
+                                if is_PyObject(restype):
+                                    return None
+                                else:
+                                    return api_function.error_value
                     else:
+                        # convert to a wrapped object
                         arg = input_arg
                     newargs += (arg, )
                 try:
                             return api_function.error_value
                     if not we_are_translated():
                         got_integer = isinstance(res, (int, long, float))
-                        assert got_integer == expect_integer
+                        assert got_integer == expect_integer,'got %r not integer' % res
                     if res is None:
                         return None
                     elif isinstance(res, Reference):
     'PyThread_ReInitTLS',
 
     'PyStructSequence_InitType', 'PyStructSequence_New',
+
+    'PyFunction_Type', 'PyMethod_Type', 'PyRange_Type', 'PyTraceBack_Type',
+
+    'PyArray_Type', '_PyArray_FILLWBYTE', '_PyArray_ZEROS', '_PyArray_CopyInto',
+
+    'Py_DebugFlag', 'Py_VerboseFlag', 'Py_InteractiveFlag', 'Py_InspectFlag',
+    'Py_OptimizeFlag', 'Py_NoSiteFlag', 'Py_BytesWarningFlag', 'Py_UseClassExceptionsFlag',
+    'Py_FrozenFlag', 'Py_TabcheckFlag', 'Py_UnicodeFlag', 'Py_IgnoreEnvironmentFlag',
+    'Py_DivisionWarningFlag', 'Py_DontWriteBytecodeFlag', 'Py_NoUserSiteDirectory',
+    '_Py_QnewFlag', 'Py_Py3kWarningFlag', 'Py_HashRandomizationFlag', '_Py_PackageContext',
 ]
 TYPES = {}
 GLOBALS = { # this needs to include all prebuilt pto, otherwise segfaults occur
                                source_dir / "capsule.c",
                                source_dir / "pysignals.c",
                                source_dir / "pythread.c",
+                               source_dir / "ndarrayobject.c",
+                               source_dir / "missing.c",
                                ],
         separate_module_sources=separate_module_sources,
         export_symbols=export_symbols_eci,

File pypy/module/cpyext/floatobject.py

File contents unchanged.

File pypy/module/cpyext/include/Python.h

 #include "pysignals.h"
 #include "pythread.h"
 
+/* Missing definitions */
+#include "missing.h"
+
 // XXX This shouldn't be included here
 #include "structmember.h"
 

File pypy/module/cpyext/include/boolobject.h

 extern "C" {
 #endif
 
+#define PyBoolObject PyIntObject
+
 #define Py_False ((PyObject *) &_Py_ZeroStruct)
 #define Py_True ((PyObject *) &_Py_TrueStruct)
 

File pypy/module/cpyext/include/complexobject.h

 extern "C" {
 #endif
 
+/* fake PyComplexObject so that code that doesn't do direct field access works */
+#define PyComplexObject PyObject
+
 typedef struct Py_complex_t {
     double real;
     double imag;
 
 /* generated function */
 PyAPI_FUNC(void) _PyComplex_AsCComplex(PyObject *, Py_complex *);
+PyAPI_FUNC(PyObject *) _PyComplex_FromCComplex(Py_complex *);
 
 Py_LOCAL_INLINE(Py_complex) PyComplex_AsCComplex(PyObject *obj)
 {
     return result;
 }
 
-#define PyComplex_FromCComplex(c) _PyComplex_FromCComplex(&c)
+// shmuller 2013/07/30: Make a function, since macro will fail in C++ due to 
+//                      const correctness if called with "const Py_complex"
+//#define PyComplex_FromCComplex(c) _PyComplex_FromCComplex(&c)
+Py_LOCAL_INLINE(PyObject *) PyComplex_FromCComplex(Py_complex c) {
+    return _PyComplex_FromCComplex(&c);
+}
 
 #ifdef __cplusplus
 }

File pypy/module/cpyext/include/funcobject.h

     PyObject *func_name;	/* The __name__ attribute, a string object */
 } PyFunctionObject;
 
+PyAPI_DATA(PyTypeObject) PyFunction_Type;
+
 #define PyFunction_GET_CODE(obj) PyFunction_GetCode((PyObject*)(obj))
 
 #define PyMethod_GET_FUNCTION(obj) PyMethod_Function((PyObject*)(obj))

File pypy/module/cpyext/include/missing.h

+
+/* Definitions from missing header files */
+
+#ifndef Py_MISSING_H
+#define Py_MISSING_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_DATA(PyTypeObject) PyMethod_Type;
+PyAPI_DATA(PyTypeObject) PyRange_Type;
+PyAPI_DATA(PyTypeObject) PyTraceBack_Type;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_MISSING_H */

File pypy/module/cpyext/include/modsupport.h

 #define PyMODINIT_FUNC void
 #endif
 
+PyAPI_DATA(char *) _Py_PackageContext;
 
 #ifdef __cplusplus
 }

File pypy/module/cpyext/include/numpy/arrayobject.h

+
+/* NDArray object interface - S. H. Muller, 2013/07/26 */
+
+#ifndef Py_NDARRAYOBJECT_H
+#define Py_NDARRAYOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "old_defines.h"
+
+#define NPY_INLINE
+#define NPY_UNUSED(x) x
+#define PyArray_MAX(a,b) (((a)>(b))?(a):(b))
+#define PyArray_MIN(a,b) (((a)<(b))?(a):(b))
+
+/* fake PyArrayObject so that code that doesn't do direct field access works */
+#define PyArrayObject PyObject
+#define PyArray_Descr PyObject
+
+extern 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
+
+#define NPY_MAXDIMS 32
+
+typedef struct {
+    npy_intp *ptr;
+    int len;
+} PyArray_Dims;
+
+/* data types copied from numpy/ndarraytypes.h 
+ * keep numbers in sync with micronumpy.interp_dtype.DTypeCache
+ */
+enum NPY_TYPES {    NPY_BOOL=0,
+                    NPY_BYTE, NPY_UBYTE,
+                    NPY_SHORT, NPY_USHORT,
+                    NPY_INT, NPY_UINT,
+                    NPY_LONG, NPY_ULONG,
+                    NPY_LONGLONG, NPY_ULONGLONG,
+                    NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE,
+                    NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE,
+                    NPY_OBJECT=17,
+                    NPY_STRING, NPY_UNICODE,
+                    NPY_VOID,
+                    /*
+                     * New 1.6 types appended, may be integrated
+                     * into the above in 2.0.
+                     */
+                    NPY_DATETIME, NPY_TIMEDELTA, NPY_HALF,
+
+                    NPY_NTYPES,
+                    NPY_NOTYPE,
+                    NPY_CHAR,      /* special flag */
+                    NPY_USERDEF=256,  /* leave room for characters */
+
+                    /* The number of types not including the new 1.6 types */
+                    NPY_NTYPES_ABI_COMPATIBLE=21
+};
+
+#define NPY_INT8      NPY_BYTE
+#define NPY_UINT8     NPY_UBYTE
+#define NPY_INT16     NPY_SHORT
+#define NPY_UINT16    NPY_USHORT
+#define NPY_INT32     NPY_INT
+#define NPY_UINT32    NPY_UINT
+#define NPY_INT64     NPY_LONG
+#define NPY_UINT64    NPY_ULONG
+#define NPY_FLOAT32   NPY_FLOAT
+#define NPY_FLOAT64   NPY_DOUBLE
+#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)))
+
+
+/* flags */
+#define NPY_ARRAY_C_CONTIGUOUS    0x0001
+#define NPY_ARRAY_F_CONTIGUOUS    0x0002
+#define NPY_ARRAY_OWNDATA         0x0004
+#define NPY_ARRAY_FORCECAST       0x0010
+#define NPY_ARRAY_ENSURECOPY      0x0020
+#define NPY_ARRAY_ENSUREARRAY     0x0040
+#define NPY_ARRAY_ELEMENTSTRIDES  0x0080
+#define NPY_ARRAY_ALIGNED         0x0100
+#define NPY_ARRAY_NOTSWAPPED      0x0200
+#define NPY_ARRAY_WRITEABLE       0x0400
+#define NPY_ARRAY_UPDATEIFCOPY    0x1000
+
+#define NPY_ARRAY_BEHAVED      (NPY_ARRAY_ALIGNED | \
+                                NPY_ARRAY_WRITEABLE)
+#define NPY_ARRAY_BEHAVED_NS   (NPY_ARRAY_ALIGNED | \
+                                NPY_ARRAY_WRITEABLE | \
+                                NPY_ARRAY_NOTSWAPPED)
+#define NPY_ARRAY_CARRAY       (NPY_ARRAY_C_CONTIGUOUS | \
+                                NPY_ARRAY_BEHAVED)
+#define NPY_ARRAY_CARRAY_RO    (NPY_ARRAY_C_CONTIGUOUS | \
+                                NPY_ARRAY_ALIGNED)
+#define NPY_ARRAY_FARRAY       (NPY_ARRAY_F_CONTIGUOUS | \
+                                NPY_ARRAY_BEHAVED)
+#define NPY_ARRAY_FARRAY_RO    (NPY_ARRAY_F_CONTIGUOUS | \
+                                NPY_ARRAY_ALIGNED)
+#define NPY_ARRAY_DEFAULT      (NPY_ARRAY_CARRAY)
+#define NPY_ARRAY_IN_ARRAY     (NPY_ARRAY_CARRAY_RO)
+#define NPY_ARRAY_OUT_ARRAY    (NPY_ARRAY_CARRAY)
+#define NPY_ARRAY_INOUT_ARRAY  (NPY_ARRAY_CARRAY | \
+                                NPY_ARRAY_UPDATEIFCOPY)
+#define NPY_ARRAY_IN_FARRAY    (NPY_ARRAY_FARRAY_RO)
+#define NPY_ARRAY_OUT_FARRAY   (NPY_ARRAY_FARRAY)
+#define NPY_ARRAY_INOUT_FARRAY (NPY_ARRAY_FARRAY | \
+                                NPY_ARRAY_UPDATEIFCOPY)
+
+#define NPY_ARRAY_UPDATE_ALL   (NPY_ARRAY_C_CONTIGUOUS | \
+                                NPY_ARRAY_F_CONTIGUOUS | \
+                                NPY_ARRAY_ALIGNED)
+
+#define NPY_FARRAY NPY_ARRAY_FARRAY
+#define NPY_CARRAY NPY_ARRAY_CARRAY
+
+#define PyArray_CHKFLAGS(m, flags) (PyArray_FLAGS(m) & (flags))
+
+#define PyArray_ISCONTIGUOUS(m) PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)
+#define PyArray_ISWRITEABLE(m) PyArray_CHKFLAGS(m, NPY_ARRAY_WRITEABLE)
+#define PyArray_ISALIGNED(m) PyArray_CHKFLAGS(m, NPY_ARRAY_ALIGNED)
+
+#define PyArray_IS_C_CONTIGUOUS(m) PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)
+#define PyArray_IS_F_CONTIGUOUS(m) PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS)
+
+#define PyArray_FLAGSWAP(m, flags) (PyArray_CHKFLAGS(m, flags) &&       \
+                                    PyArray_ISNOTSWAPPED(m))
+
+#define PyArray_ISCARRAY(m) PyArray_FLAGSWAP(m, NPY_ARRAY_CARRAY)
+#define PyArray_ISCARRAY_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_CARRAY_RO)
+#define PyArray_ISFARRAY(m) PyArray_FLAGSWAP(m, NPY_ARRAY_FARRAY)
+#define PyArray_ISFARRAY_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_FARRAY_RO)
+#define PyArray_ISBEHAVED(m) PyArray_FLAGSWAP(m, NPY_ARRAY_BEHAVED)
+#define PyArray_ISBEHAVED_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_ALIGNED)
+
+#define PyArray_ISONESEGMENT(arr)  (1)
+#define PyArray_ISNOTSWAPPED(arr)  (1)
+#define PyArray_ISBYTESWAPPED(arr) (0)
+
+
+/* functions */
+#ifndef PyArray_NDIM
+
+#define PyArray_Check      _PyArray_Check
+#define PyArray_CheckExact _PyArray_CheckExact
+#define PyArray_FLAGS      _PyArray_FLAGS
+
+#define PyArray_NDIM       _PyArray_NDIM
+#define PyArray_DIM        _PyArray_DIM
+#define PyArray_STRIDE     _PyArray_STRIDE
+#define PyArray_SIZE       _PyArray_SIZE
+#define PyArray_ITEMSIZE   _PyArray_ITEMSIZE
+#define PyArray_NBYTES     _PyArray_NBYTES
+#define PyArray_TYPE       _PyArray_TYPE
+#define PyArray_DATA       _PyArray_DATA
+
+#define PyArray_Size PyArray_SIZE
+#define PyArray_BYTES(arr) ((char *)PyArray_DATA(arr))
+
+#define PyArray_FromAny _PyArray_FromAny
+#define PyArray_FromObject _PyArray_FromObject
+#define PyArray_ContiguousFromObject PyArray_FromObject
+#define PyArray_ContiguousFromAny PyArray_FromObject
+
+#define PyArray_FROMANY(obj, typenum, min, max, 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
+
+#define PyArray_EMPTY(nd, dims, type_num, fortran) \
+        PyArray_SimpleNew(nd, dims, type_num)
+
+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)
+
+/* Don't use these in loops! */
+
+#define PyArray_GETPTR1(obj, i) ((void *)(PyArray_BYTES(obj) + \
+                                         (i)*PyArray_STRIDE(obj,0)))
+
+#define PyArray_GETPTR2(obj, i, j) ((void *)(PyArray_BYTES(obj) + \
+                                            (i)*PyArray_STRIDE(obj,0) + \
+                                            (j)*PyArray_STRIDE(obj,1)))
+
+#define PyArray_GETPTR3(obj, i, j, k) ((void *)(PyArray_BYTES(obj) + \
+                                            (i)*PyArray_STRIDE(obj,0) + \
+                                            (j)*PyArray_STRIDE(obj,1) + \
+                                            (k)*PyArray_STRIDE(obj,2)))
+
+#define PyArray_GETPTR4(obj, i, j, k, l) ((void *)(PyArray_BYTES(obj) + \
+                                            (i)*PyArray_STRIDE(obj,0) + \
+                                            (j)*PyArray_STRIDE(obj,1) + \
+                                            (k)*PyArray_STRIDE(obj,2) + \
+                                            (l)*PyArray_STRIDE(obj,3)))
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_NDARRAYOBJECT_H */

File pypy/module/cpyext/include/numpy/npy_3kcompat.h

Empty file added.

File pypy/module/cpyext/include/numpy/old_defines.h

+/* This header is deprecated as of NumPy 1.7 */
+#ifndef OLD_DEFINES_H
+#define OLD_DEFINES_H
+
+/*
+#if defined(NPY_NO_DEPRECATED_API) && NPY_NO_DEPRECATED_API >= NPY_1_7_API_VERSION
+#error The header "old_defines.h" is deprecated as of NumPy 1.7.
+#endif
+*/
+
+#define NDARRAY_VERSION NPY_VERSION
+
+#define PyArray_MIN_BUFSIZE NPY_MIN_BUFSIZE
+#define PyArray_MAX_BUFSIZE NPY_MAX_BUFSIZE
+#define PyArray_BUFSIZE NPY_BUFSIZE
+
+#define PyArray_PRIORITY NPY_PRIORITY
+#define PyArray_SUBTYPE_PRIORITY NPY_PRIORITY
+#define PyArray_NUM_FLOATTYPE NPY_NUM_FLOATTYPE
+
+#define NPY_MAX PyArray_MAX
+#define NPY_MIN PyArray_MIN
+
+#define PyArray_TYPES       NPY_TYPES
+#define PyArray_BOOL        NPY_BOOL
+#define PyArray_BYTE        NPY_BYTE
+#define PyArray_UBYTE       NPY_UBYTE
+#define PyArray_SHORT       NPY_SHORT
+#define PyArray_USHORT      NPY_USHORT
+#define PyArray_INT         NPY_INT
+#define PyArray_UINT        NPY_UINT
+#define PyArray_LONG        NPY_LONG
+#define PyArray_ULONG       NPY_ULONG
+#define PyArray_LONGLONG    NPY_LONGLONG
+#define PyArray_ULONGLONG   NPY_ULONGLONG
+#define PyArray_HALF        NPY_HALF
+#define PyArray_FLOAT       NPY_FLOAT
+#define PyArray_DOUBLE      NPY_DOUBLE
+#define PyArray_LONGDOUBLE  NPY_LONGDOUBLE
+#define PyArray_CFLOAT      NPY_CFLOAT
+#define PyArray_CDOUBLE     NPY_CDOUBLE
+#define PyArray_CLONGDOUBLE NPY_CLONGDOUBLE
+#define PyArray_OBJECT      NPY_OBJECT
+#define PyArray_STRING      NPY_STRING
+#define PyArray_UNICODE     NPY_UNICODE
+#define PyArray_VOID        NPY_VOID
+#define PyArray_DATETIME    NPY_DATETIME
+#define PyArray_TIMEDELTA   NPY_TIMEDELTA
+#define PyArray_NTYPES      NPY_NTYPES
+#define PyArray_NOTYPE      NPY_NOTYPE
+#define PyArray_CHAR        NPY_CHAR
+#define PyArray_USERDEF     NPY_USERDEF
+#define PyArray_NUMUSERTYPES NPY_NUMUSERTYPES
+
+#define PyArray_INTP        NPY_INTP
+#define PyArray_UINTP       NPY_UINTP
+
+#define PyArray_INT8    NPY_INT8
+#define PyArray_UINT8   NPY_UINT8
+#define PyArray_INT16   NPY_INT16
+#define PyArray_UINT16  NPY_UINT16
+#define PyArray_INT32   NPY_INT32
+#define PyArray_UINT32  NPY_UINT32
+
+#ifdef NPY_INT64
+#define PyArray_INT64   NPY_INT64
+#define PyArray_UINT64  NPY_UINT64
+#endif
+
+#ifdef NPY_INT128
+#define PyArray_INT128 NPY_INT128
+#define PyArray_UINT128 NPY_UINT128
+#endif
+
+#ifdef NPY_FLOAT16
+#define PyArray_FLOAT16  NPY_FLOAT16
+#define PyArray_COMPLEX32  NPY_COMPLEX32
+#endif
+
+#ifdef NPY_FLOAT80
+#define PyArray_FLOAT80  NPY_FLOAT80
+#define PyArray_COMPLEX160  NPY_COMPLEX160
+#endif
+
+#ifdef NPY_FLOAT96
+#define PyArray_FLOAT96  NPY_FLOAT96
+#define PyArray_COMPLEX192  NPY_COMPLEX192
+#endif
+
+#ifdef NPY_FLOAT128
+#define PyArray_FLOAT128  NPY_FLOAT128
+#define PyArray_COMPLEX256  NPY_COMPLEX256
+#endif
+
+#define PyArray_FLOAT32    NPY_FLOAT32
+#define PyArray_COMPLEX64  NPY_COMPLEX64
+#define PyArray_FLOAT64    NPY_FLOAT64
+#define PyArray_COMPLEX128 NPY_COMPLEX128
+
+
+#define PyArray_TYPECHAR        NPY_TYPECHAR
+#define PyArray_BOOLLTR         NPY_BOOLLTR
+#define PyArray_BYTELTR         NPY_BYTELTR
+#define PyArray_UBYTELTR        NPY_UBYTELTR
+#define PyArray_SHORTLTR        NPY_SHORTLTR
+#define PyArray_USHORTLTR       NPY_USHORTLTR
+#define PyArray_INTLTR          NPY_INTLTR
+#define PyArray_UINTLTR         NPY_UINTLTR
+#define PyArray_LONGLTR         NPY_LONGLTR
+#define PyArray_ULONGLTR        NPY_ULONGLTR
+#define PyArray_LONGLONGLTR     NPY_LONGLONGLTR
+#define PyArray_ULONGLONGLTR    NPY_ULONGLONGLTR
+#define PyArray_HALFLTR         NPY_HALFLTR
+#define PyArray_FLOATLTR        NPY_FLOATLTR
+#define PyArray_DOUBLELTR       NPY_DOUBLELTR
+#define PyArray_LONGDOUBLELTR   NPY_LONGDOUBLELTR
+#define PyArray_CFLOATLTR       NPY_CFLOATLTR
+#define PyArray_CDOUBLELTR      NPY_CDOUBLELTR
+#define PyArray_CLONGDOUBLELTR  NPY_CLONGDOUBLELTR
+#define PyArray_OBJECTLTR       NPY_OBJECTLTR
+#define PyArray_STRINGLTR       NPY_STRINGLTR
+#define PyArray_STRINGLTR2      NPY_STRINGLTR2
+#define PyArray_UNICODELTR      NPY_UNICODELTR
+#define PyArray_VOIDLTR         NPY_VOIDLTR
+#define PyArray_DATETIMELTR     NPY_DATETIMELTR
+#define PyArray_TIMEDELTALTR    NPY_TIMEDELTALTR
+#define PyArray_CHARLTR         NPY_CHARLTR
+#define PyArray_INTPLTR         NPY_INTPLTR
+#define PyArray_UINTPLTR        NPY_UINTPLTR
+#define PyArray_GENBOOLLTR      NPY_GENBOOLLTR
+#define PyArray_SIGNEDLTR       NPY_SIGNEDLTR
+#define PyArray_UNSIGNEDLTR     NPY_UNSIGNEDLTR
+#define PyArray_FLOATINGLTR     NPY_FLOATINGLTR
+#define PyArray_COMPLEXLTR      NPY_COMPLEXLTR
+
+#define PyArray_QUICKSORT   NPY_QUICKSORT
+#define PyArray_HEAPSORT    NPY_HEAPSORT
+#define PyArray_MERGESORT   NPY_MERGESORT
+#define PyArray_SORTKIND    NPY_SORTKIND
+#define PyArray_NSORTS      NPY_NSORTS
+
+#define PyArray_NOSCALAR       NPY_NOSCALAR
+#define PyArray_BOOL_SCALAR    NPY_BOOL_SCALAR
+#define PyArray_INTPOS_SCALAR  NPY_INTPOS_SCALAR
+#define PyArray_INTNEG_SCALAR  NPY_INTNEG_SCALAR
+#define PyArray_FLOAT_SCALAR   NPY_FLOAT_SCALAR
+#define PyArray_COMPLEX_SCALAR NPY_COMPLEX_SCALAR
+#define PyArray_OBJECT_SCALAR  NPY_OBJECT_SCALAR
+#define PyArray_SCALARKIND     NPY_SCALARKIND
+#define PyArray_NSCALARKINDS   NPY_NSCALARKINDS
+
+#define PyArray_ANYORDER     NPY_ANYORDER
+#define PyArray_CORDER       NPY_CORDER
+#define PyArray_FORTRANORDER NPY_FORTRANORDER
+#define PyArray_ORDER        NPY_ORDER
+
+#define PyDescr_ISBOOL      PyDataType_ISBOOL
+#define PyDescr_ISUNSIGNED  PyDataType_ISUNSIGNED
+#define PyDescr_ISSIGNED    PyDataType_ISSIGNED
+#define PyDescr_ISINTEGER   PyDataType_ISINTEGER
+#define PyDescr_ISFLOAT     PyDataType_ISFLOAT
+#define PyDescr_ISNUMBER    PyDataType_ISNUMBER
+#define PyDescr_ISSTRING    PyDataType_ISSTRING
+#define PyDescr_ISCOMPLEX   PyDataType_ISCOMPLEX
+#define PyDescr_ISPYTHON    PyDataType_ISPYTHON
+#define PyDescr_ISFLEXIBLE  PyDataType_ISFLEXIBLE
+#define PyDescr_ISUSERDEF   PyDataType_ISUSERDEF
+#define PyDescr_ISEXTENDED  PyDataType_ISEXTENDED
+#define PyDescr_ISOBJECT    PyDataType_ISOBJECT
+#define PyDescr_HASFIELDS   PyDataType_HASFIELDS
+
+#define PyArray_LITTLE NPY_LITTLE
+#define PyArray_BIG NPY_BIG
+#define PyArray_NATIVE NPY_NATIVE
+#define PyArray_SWAP NPY_SWAP
+#define PyArray_IGNORE NPY_IGNORE
+
+#define PyArray_NATBYTE NPY_NATBYTE
+#define PyArray_OPPBYTE NPY_OPPBYTE
+
+#define PyArray_MAX_ELSIZE NPY_MAX_ELSIZE
+
+#define PyArray_USE_PYMEM NPY_USE_PYMEM
+
+#define PyArray_RemoveLargest PyArray_RemoveSmallest
+
+#define PyArray_UCS4 npy_ucs4
+
+#endif

File pypy/module/cpyext/include/pythonrun.h

 extern "C" {
 #endif
 
-  void Py_FatalError(const char *msg);
+void Py_FatalError(const char *msg);
 
-/* the -3 option will probably not be implemented */
-#define Py_Py3kWarningFlag 0
+/* taken from Python-2.7.3/Include/pydebug.h */
+PyAPI_DATA(int) Py_DebugFlag;
+PyAPI_DATA(int) Py_VerboseFlag;
+PyAPI_DATA(int) Py_InteractiveFlag;
+PyAPI_DATA(int) Py_InspectFlag;
+PyAPI_DATA(int) Py_OptimizeFlag;
+PyAPI_DATA(int) Py_NoSiteFlag;
+PyAPI_DATA(int) Py_BytesWarningFlag;
+PyAPI_DATA(int) Py_UseClassExceptionsFlag;
+PyAPI_DATA(int) Py_FrozenFlag;
+PyAPI_DATA(int) Py_TabcheckFlag;
+PyAPI_DATA(int) Py_UnicodeFlag;
+PyAPI_DATA(int) Py_IgnoreEnvironmentFlag;
+PyAPI_DATA(int) Py_DivisionWarningFlag;
+PyAPI_DATA(int) Py_DontWriteBytecodeFlag;
+PyAPI_DATA(int) Py_NoUserSiteDirectory;
+/* _XXX Py_QnewFlag should go away in 3.0.  It's true iff -Qnew is passed,
+ *   on the command line, and is used in 2.2 by ceval.c to make all "/" divisions
+ *     true divisions (which they will be in 3.0). */
+PyAPI_DATA(int) _Py_QnewFlag;
+/* Warn about 3.x issues */
+PyAPI_DATA(int) Py_Py3kWarningFlag;
+PyAPI_DATA(int) Py_HashRandomizationFlag;
 
-#define Py_FrozenFlag 0
-#define Py_VerboseFlag 0
-#define Py_DebugFlag 1
 
 typedef struct {
     int cf_flags;  /* bitmask of CO_xxx flags relevant to future */

File pypy/module/cpyext/ndarrayobject.py

+"""
+
+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.api import PyObject
+from pypy.module.micronumpy.interp_numarray import W_NDimArray, array
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache, W_Dtype
+from pypy.module.micronumpy.arrayimpl.concrete import ConcreteArray
+from pypy.module.micronumpy.arrayimpl.scalar import Scalar
+from rpython.rlib.rawstorage import RAW_STORAGE_PTR
+
+NPY_C_CONTIGUOUS   = 0x0001
+NPY_F_CONTIGUOUS   = 0x0002
+NPY_OWNDATA        = 0x0004
+NPY_FORCECAST      = 0x0010
+NPY_ENSURECOPY     = 0x0020
+NPY_ENSUREARRAY    = 0x0040
+NPY_ELEMENTSTRIDES = 0x0080
+NPY_ALIGNED        = 0x0100
+NPY_NOTSWAPPED     = 0x0200
+NPY_WRITEABLE      = 0x0400
+NPY_UPDATEIFCOPY   = 0x1000
+
+NPY_BEHAVED      = NPY_ALIGNED | NPY_WRITEABLE
+NPY_BEHAVED_NS   = NPY_ALIGNED | NPY_WRITEABLE | NPY_NOTSWAPPED
+NPY_CARRAY       = NPY_C_CONTIGUOUS | NPY_BEHAVED
+NPY_CARRAY_RO    = NPY_C_CONTIGUOUS | NPY_ALIGNED
+NPY_FARRAY       = NPY_F_CONTIGUOUS | NPY_BEHAVED
+NPY_FARRAY_RO    = NPY_F_CONTIGUOUS | NPY_ALIGNED
+NPY_DEFAULT      = NPY_CARRAY
+NPY_IN           = NPY_CARRAY_RO
+NPY_OUT          = NPY_CARRAY
+NPY_INOUT        = NPY_CARRAY | NPY_UPDATEIFCOPY
+NPY_IN_FARRAY    = NPY_FARRAY_RO
+NPY_OUT_FARRAY   = NPY_FARRAY
+NPY_INOUT_FARRAY = NPY_FARRAY | NPY_UPDATEIFCOPY
+NPY_CONTIGUOUS   = NPY_C_CONTIGUOUS | NPY_F_CONTIGUOUS
+NPY_UPDATE_ALL   = NPY_CONTIGUOUS | NPY_ALIGNED
+
+
+# the asserts are needed, otherwise the translation fails
+
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def _PyArray_Check(space, w_obj):
+    w_obj_type = space.type(w_obj)
+    w_type = space.gettypeobject(W_NDimArray.typedef)
+    return (space.is_w(w_obj_type, w_type) or
+            space.is_true(space.issubtype(w_obj_type, w_type)))
+
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def _PyArray_CheckExact(space, w_obj):
+    w_obj_type = space.type(w_obj)
+    w_type = space.gettypeobject(W_NDimArray.typedef)
+    return space.is_w(w_obj_type, w_type)
+
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def _PyArray_FLAGS(space, w_array):
+    assert isinstance(w_array, W_NDimArray)
+    flags = NPY_BEHAVED_NS
+    if isinstance(w_array.implementation, ConcreteArray):
+        flags |= NPY_OWNDATA
+    if len(w_array.get_shape()) < 2:
+        flags |= NPY_CONTIGUOUS
+    elif w_array.implementation.order == 'C':
+        flags |= NPY_C_CONTIGUOUS
+    else:
+        flags |= NPY_F_CONTIGUOUS
+    return flags
+
+@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())
+
+@cpython_api([PyObject, Py_ssize_t], Py_ssize_t, error=CANNOT_FAIL)
+def _PyArray_DIM(space, w_array, n):
+    assert isinstance(w_array, W_NDimArray)
+    return w_array.get_shape()[n]
+
+@cpython_api([PyObject, Py_ssize_t], Py_ssize_t, error=CANNOT_FAIL)
+def _PyArray_STRIDE(space, w_array, n):
+    assert isinstance(w_array, W_NDimArray)
+    return w_array.implementation.get_strides()[n]
+
+@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+def _PyArray_SIZE(space, w_array):
+    assert isinstance(w_array, W_NDimArray)
+    return w_array.get_size()
+
+@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()
+
+@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+def _PyArray_NBYTES(space, w_array):
+    assert isinstance(w_array, W_NDimArray)
+    return w_array.get_size() * w_array.get_dtype().get_size()
+
+@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
+
+
+@cpython_api([PyObject], rffi.VOIDP, error=CANNOT_FAIL)
+def _PyArray_DATA(space, w_array):
+    # fails on scalars - see PyArray_FromAny()
+    assert isinstance(w_array, W_NDimArray)
+    return rffi.cast(rffi.VOIDP, w_array.implementation.storage)
+
+PyArray_Descr = PyObject
+NULL = lltype.nullptr(rffi.VOIDP.TO)
+
+@cpython_api([PyObject, PyArray_Descr, Py_ssize_t, Py_ssize_t, Py_ssize_t, rffi.VOIDP],
+             PyObject)
+def _PyArray_FromAny(space, w_obj, w_dtype, min_depth, max_depth, requirements, context):
+    """ This is the main function used to obtain an array from any nested
+         sequence, or object that exposes the array interface, op. The
+         parameters allow specification of the required dtype, the
+         minimum (min_depth) and maximum (max_depth) number of dimensions
+         acceptable, and other requirements for the array.
+
+         The dtype argument needs to be a PyArray_Descr structure indicating
+         the desired data-type (including required byteorder). The dtype
+         argument may be NULL, indicating that any data-type (and byteorder)
+         is acceptable.
+         Unless FORCECAST is present in flags, this call will generate an error
+         if the data type cannot be safely obtained from the object. If you
+         want to use NULL for the dtype and ensure the array is notswapped then
+         use PyArray_CheckFromAny.
+
+         A value of 0 for either of the depth parameters causes the parameter
+         to be ignored.
+
+         Any of the following array flags can be added (e.g. using |) to get
+         the requirements argument. If your code can handle general (e.g.
+         strided, byte-swapped, or unaligned arrays) then requirements
+         may be 0. Also, if op is not already an array (or does not expose
+         the array interface), then a new array will be created (and filled
+         from op using the sequence protocol). The new array will have
+         NPY_DEFAULT as its flags member.
+
+         The context argument is passed to the __array__ method of op and is
+         only used if the array is constructed that way. Almost always this
+         parameter is NULL.
+    """
+    if min_depth !=0 or max_depth != 0:
+        raise OperationError(space.w_NotImplementedError, space.wrap(
+            '_PyArray_FromAny called with not-implemented min_dpeth or max_depth argument'))
+    if requirements not in (0, NPY_DEFAULT):
+        raise OperationError(space.w_NotImplementedError, space.wrap(
+            '_PyArray_FromAny called with not-implemented requirements argument'))
+    w_array = array(space, w_obj, w_dtype=w_dtype, copy=False)
+    if w_array.is_scalar():
+        # since PyArray_DATA() fails on scalars, create a 1D array and set empty
+        # shape. So the following combination works for *reading* scalars:
+        #     PyObject *arr = PyArray_FromAny(obj);
+        #     int nd = PyArray_NDIM(arr);
+        #     void *data = PyArray_DATA(arr);
+        impl = w_array.implementation
+        w_array = W_NDimArray.from_shape(space, [1], impl.dtype)
+        w_array.implementation.setitem(0, impl.value)
+        w_array.implementation.shape = []
+    return w_array
+
+@cpython_api([PyObject, Py_ssize_t, Py_ssize_t, Py_ssize_t], PyObject)
+def _PyArray_FromObject(space, w_obj, typenum, min_depth, max_depth):
+    try:
+        dtype = get_dtype_cache(space).dtypes_by_num[typenum]
+    except KeyError:
+        raise OperationError(space.w_ValueError, space.wrap(
+            '_PyArray_FromObject called with invalid dtype %d' % typenum))
+    try:
+        return _PyArray_FromAny(space, w_obj, dtype, min_depth, max_depth,
+                            0, NULL);
+    except OperationError, e:
+        if e.match(space, space.w_NotImplementedError):
+            errstr = space.str_w(e.get_w_value(space))
+            errstr = '_PyArray_FromObject' + errstr[16:]
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                errstr))
+        raise
+
+def get_shape_and_dtype(space, nd, dims, typenum):
+    shape = []
+    for i in range(nd):
+        shape.append(rffi.cast(rffi.LONG, 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,
+        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:
+        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):
+    return simple_new_from_data(space, nd, dims, typenum, data, owning=False)
+
+@cpython_api([Py_ssize_t, rffi.LONGP, Py_ssize_t, rffi.VOIDP], PyObject)
+def _PyArray_SimpleNewFromDataOwning(space, nd, dims, typenum, data):
+    # Variant to take over ownership of the memory, equivalent to:
+    #     PyObject *arr = PyArray_SimpleNewFromData(nd, dims, typenum, data);
+    #     ((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 = 'C' if flags & NPY_C_CONTIGUOUS else 'F'
+    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)
+

File pypy/module/cpyext/number.py

 from pypy.interpreter.error import OperationError
 from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, Py_ssize_t
-from pypy.module.cpyext.pyobject import PyObject
+from pypy.module.cpyext.pyobject import PyObject, PyObjectP, from_ref, make_ref, Py_DecRef
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.tool.sourcetools import func_with_new_name
+from pypy.module.cpyext.state import State
 
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyIndex_Check(space, w_obj):
     """
     return space.index(w_obj)
 
+@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=CANNOT_FAIL)
+def PyNumber_CoerceEx(space, pp1, pp2):
+    """This function is similar to PyNumber_Coerce(), except that it returns
+    1 when the conversion is not possible and when no error is raised.
+    Reference counts are still not increased in this case."""
+    retVal = PyNumber_Coerce(space, pp1, pp2)
+    if retVal != 0:
+        return 1
+    return 0
+
+@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=CANNOT_FAIL)
+def PyNumber_Coerce(space, pp1, pp2):
+    """This function takes the addresses of two variables of type PyObject*.  If
+    the objects pointed to by *p1 and *p2 have the same type, increment their
+    reference count and return 0 (success). If the objects can be converted to a
+    common numeric type, replace *p1 and *p2 by their converted value (with
+    'new' reference counts), and return 0. If no conversion is possible, or if
+    some other error occurs, return -1 (failure) and don't increment the
+    reference counts.  The call PyNumber_Coerce(&o1, &o2) is equivalent to the
+    Python statement o1, o2 = coerce(o1, o2)."""
+    w_obj1 = from_ref(space, pp1[0])
+    w_obj2 = from_ref(space, pp2[0])
+    try:
+        w_res = space.coerce(w_obj1, w_obj2)
+    except (TypeError, OperationError):
+        state = space.fromcache(State)
+        state.clear_exception()
+        return -1
+    w_res1, w_res2 = space.unpackiterable(w_res, 2)
+    pp1[0] = make_ref(space, w_res1)
+    pp2[0] = make_ref(space, w_res2)
+    return 0
+
 def func_rename(newname):
     return lambda func: func_with_new_name(func, newname)
 

File pypy/module/cpyext/src/missing.c

+/* Definitions of missing symbols go here */
+
+#include "Python.h"
+
+PyTypeObject PyFunction_Type;
+
+PyTypeObject PyMethod_Type;
+PyTypeObject PyRange_Type;
+PyTypeObject PyTraceBack_Type;
+
+int Py_DebugFlag = 1;
+int Py_VerboseFlag = 0;
+int Py_InteractiveFlag = 0;
+int Py_InspectFlag = 0;
+int Py_OptimizeFlag = 0;
+int Py_NoSiteFlag = 0;
+int Py_BytesWarningFlag = 0;
+int Py_UseClassExceptionsFlag = 0;
+int Py_FrozenFlag = 0;
+int Py_TabcheckFlag = 0;
+int Py_UnicodeFlag = 0;
+int Py_IgnoreEnvironmentFlag = 0;
+int Py_DivisionWarningFlag = 0;
+int Py_DontWriteBytecodeFlag = 0;
+int Py_NoUserSiteDirectory = 0;
+int _Py_QnewFlag = 0;
+int Py_Py3kWarningFlag = 0;
+int Py_HashRandomizationFlag = 0;
+

File pypy/module/cpyext/src/modsupport.c

 
 static PyObject *va_build_value(const char *, va_list, int);
 
-/* Package context -- the full module name for package imports */
+/* Package context -- the full module name for package imports
+ * Should this be modified in  _Py_InitPyPyModule for CPython
+ * compatibility  (see CPython's Py_InitModule4)? */
 char *_Py_PackageContext = NULL;
 
 /* Py_InitModule4() parameters:

File pypy/module/cpyext/src/ndarrayobject.c

+
+#include "Python.h"
+#include "numpy/arrayobject.h"
+#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) 
+{
+    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;
+}
+

File pypy/module/cpyext/stringobject.py

     Py_DecRef(space, string[0])
     string[0] = make_ref(space, w_str)
 
-@cpython_api([PyObject, rffi.CCHARP, rffi.CCHARP], PyObject)
+@cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
 def PyString_AsEncodedObject(space, w_str, encoding, errors):
     """Encode a string object using the codec registered for encoding and return
     the result as Python object. encoding and errors have the same meaning as
         w_errors = space.wrap(rffi.charp2str(errors))
     return space.call_method(w_str, 'encode', w_encoding, w_errors)
 
-@cpython_api([PyObject, rffi.CCHARP, rffi.CCHARP], PyObject)
+@cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
 def PyString_AsDecodedObject(space, w_str, encoding, errors):
     """Decode a string object by passing it to the codec registered
     for encoding and return the result as Python object. encoding and

File pypy/module/cpyext/stubs.py

     """
     raise NotImplementedError
 
-@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=-1)
-def PyNumber_Coerce(space, p1, p2):
-    """This function takes the addresses of two variables of type PyObject*.  If
-    the objects pointed to by *p1 and *p2 have the same type, increment their
-    reference count and return 0 (success). If the objects can be converted to a
-    common numeric type, replace *p1 and *p2 by their converted value (with
-    'new' reference counts), and return 0. If no conversion is possible, or if
-    some other error occurs, return -1 (failure) and don't increment the
-    reference counts.  The call PyNumber_Coerce(&o1, &o2) is equivalent to the
-    Python statement o1, o2 = coerce(o1, o2)."""
-    raise NotImplementedError
-
-@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=-1)
-def PyNumber_CoerceEx(space, p1, p2):
-    """This function is similar to PyNumber_Coerce(), except that it returns
-    1 when the conversion is not possible and when no error is raised.
-    Reference counts are still not increased in this case."""
-    raise NotImplementedError
-
 @cpython_api([PyObject, rffi.INT_real], PyObject)
 def PyNumber_ToBase(space, n, base):
     """Returns the integer n converted to base as a string with a base

File pypy/module/cpyext/test/test_api.py

             raise Exception("DID NOT RAISE")
         if getattr(space, 'w_' + expected_exc.__name__) is not operror.w_type:
             raise Exception("Wrong exception")
-        state.clear_exception()
+        return state.clear_exception()
 
     def setup_method(self, func):
         freeze_refcnts(self)

File pypy/module/cpyext/test/test_ndarrayobject.py

+import py
+
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from rpython.rtyper.lltypesystem import rffi, lltype
+
+from pypy.module.micronumpy.interp_numarray import W_NDimArray
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+
+def scalar(space):
+    dtype = get_dtype_cache(space).w_float64dtype
+    return W_NDimArray.new_scalar(space, dtype, space.wrap(10.))
+
+def array(space, shape, order='C'):
+    dtype = get_dtype_cache(space).w_float64dtype
+    return W_NDimArray.from_shape(space, shape, dtype, order=order)
+
+def iarray(space, shape, order='C'):
+    dtype = get_dtype_cache(space).w_int64dtype
+    return W_NDimArray.from_shape(space, shape, dtype, order=order)
+
+
+NULL = lltype.nullptr(rffi.VOIDP.TO)
+
+class TestNDArrayObject(BaseApiTest):
+
+    def test_Check(self, space, api):
+        a = array(space, [10, 5, 3])
+        x = space.wrap(10.)
+        assert api._PyArray_Check(a)
+        assert api._PyArray_CheckExact(a)
+        assert not api._PyArray_Check(x)
+        assert not api._PyArray_CheckExact(x)
+
+    def test_FLAGS(self, space, api):
+        s = array(space, [10])
+        c = array(space, [10, 5, 3], order='C')
+        f = array(space, [10, 5, 3], order='F')
+        assert api._PyArray_FLAGS(s) & 0x0001
+        assert api._PyArray_FLAGS(s) & 0x0002
+        assert api._PyArray_FLAGS(c) & 0x0001
+        assert api._PyArray_FLAGS(f) & 0x0002
+        assert not api._PyArray_FLAGS(c) & 0x0002
+        assert not api._PyArray_FLAGS(f) & 0x0001
+
+    def test_NDIM(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_NDIM(a) == 3
+
+    def test_DIM(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_DIM(a, 1) == 5
+
+    def test_STRIDE(self, space, api):
+        a = array(space, [10, 5, 3], )
+        assert api._PyArray_STRIDE(a, 1) == a.implementation.get_strides()[1]
+
+    def test_SIZE(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_SIZE(a) == 150
+
+    def test_ITEMSIZE(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_ITEMSIZE(a) == 8
+
+    def test_NBYTES(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_NBYTES(a) == 1200
+
+    def test_TYPE(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_TYPE(a) == 12
+
+    def test_DATA(self, space, api):
+        a = array(space, [10, 5, 3])
+        addr = api._PyArray_DATA(a)
+        addr2 = rffi.cast(rffi.VOIDP, a.implementation.storage)
+        assert addr == addr2
+
+    def test_FromAny_scalar(self, space, api):
+        a0 = scalar(space)
+        assert a0.implementation.get_scalar_value().value == 10.
+
+        a = api._PyArray_FromAny(a0, NULL, 0, 0, 0, NULL)
+        assert api._PyArray_NDIM(a) == 0
+
+        ptr = rffi.cast(rffi.DOUBLEP, api._PyArray_DATA(a))
+        assert ptr[0] == 10.
+
+    def test_FromAny(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_FromAny(a, NULL, 0, 0, 0, NULL) is a
+        self.raises(space, api, NotImplementedError, api._PyArray_FromAny,
+                    a, NULL, 0, 3, 0, NULL)
+
+    def test_FromObject(self, space, api):
+        a = array(space, [10, 5, 3])
+        assert api._PyArray_FromObject(a, a.get_dtype().num, 0, 0) is a
+        exc = self.raises(space, api, NotImplementedError, api._PyArray_FromObject,
+                    a, 11, 0, 3)
+        assert exc.errorstr(space).find('FromObject') >= 0
+
+    def test_list_from_fixedptr(self, space, api):
+        A = lltype.GcArray(lltype.Float)
+        ptr = lltype.malloc(A, 3)
+        assert isinstance(ptr, lltype._ptr)
+        ptr[0] = 10.
+        ptr[1] = 5.
+        ptr[2] = 3.
+        l = list(ptr)
+        assert l == [10., 5., 3.]
+
+    def test_list_from_openptr(self, space, api):
+        nd = 3
+        a = array(space, [nd])
+        ptr = rffi.cast(rffi.DOUBLEP, api._PyArray_DATA(a))
+        ptr[0] = 10.
+        ptr[1] = 5.
+        ptr[2] = 3.
+        l = []
+        for i in range(nd):
+            l.append(ptr[i])
+        assert l == [10., 5., 3.]
+
+    def test_SimpleNew_scalar(self, space, api):
+        ptr_s = lltype.nullptr(rffi.LONGP.TO)
+        a = api._PyArray_SimpleNew(0, ptr_s, 12)
+
+        dtype = get_dtype_cache(space).w_float64dtype
+
+        a.set_scalar_value(dtype.itemtype.box(10.))
+        assert a.get_scalar_value().value == 10.
+
+    def test_SimpleNewFromData_scalar(self, space, api):
+        a = array(space, [1])
+        num = api._PyArray_TYPE(a)
+        ptr_a = api._PyArray_DATA(a)
+
+        x = rffi.cast(rffi.DOUBLEP, ptr_a)
+        x[0] = float(10.)
+
+        ptr_s = lltype.nullptr(rffi.LONGP.TO)
+
+        res = api._PyArray_SimpleNewFromData(0, ptr_s, num, ptr_a)
+        assert res.is_scalar()
+        assert res.get_scalar_value().value == 10.
+
+    def test_SimpleNew(self, space, api):
+        shape = [10, 5, 3]
+        nd = len(shape)
+
+        s = iarray(space, [nd])
+        ptr_s = rffi.cast(rffi.LONGP, api._PyArray_DATA(s))
+        ptr_s[0] = 10
+        ptr_s[1] = 5
+        ptr_s[2] = 3
+
+        a = api._PyArray_SimpleNew(nd, ptr_s, 12)
+
+        #assert list(api._PyArray_DIMS(a))[:3] == shape
+
+        ptr_a = api._PyArray_DATA(a)
+
+        x = rffi.cast(rffi.DOUBLEP, ptr_a)
+        for i in range(150):
+            x[i] = float(i)
+
+        for i in range(150):
+            assert x[i] == float(i)
+
+    def test_SimpleNewFromData(self, space, api):
+        shape = [10, 5, 3]
+        nd = len(shape)
+
+        s = iarray(space, [nd])
+        ptr_s = rffi.cast(rffi.LONGP, api._PyArray_DATA(s))
+        ptr_s[0] = 10
+        ptr_s[1] = 5
+        ptr_s[2] = 3
+
+        a = array(space, shape)
+        num = api._PyArray_TYPE(a)
+        ptr_a = api._PyArray_DATA(a)
+
+        x = rffi.cast(rffi.DOUBLEP, ptr_a)
+        for i in range(150):
+            x[i] = float(i)
+
+        res = api._PyArray_SimpleNewFromData(nd, ptr_s, num, ptr_a)
+        assert api._PyArray_TYPE(res) == num
+        assert api._PyArray_DATA(res) == ptr_a
+        for i in range(nd):
+            assert api._PyArray_DIM(res, i) == shape[i]
+        ptr_r = rffi.cast(rffi.DOUBLEP, api._PyArray_DATA(res))
+        for i in range(150):
+            assert ptr_r[i] == float(i)
+        res = api._PyArray_SimpleNewFromDataOwning(nd, ptr_s, num, ptr_a)
+        x = rffi.cast(rffi.DOUBLEP, ptr_a)
+        ptr_r = rffi.cast(rffi.DOUBLEP, api._PyArray_DATA(res))
+        x[20] = -100.
+        assert ptr_r[20] == -100.
+
+    def test_SimpleNewFromData_complex(self, space, api):
+        a = array(space, [2])
+        ptr_a = api._PyArray_DATA(a)
+
+        x = rffi.cast(rffi.DOUBLEP, ptr_a)
+        x[0] = 3.
+        x[1] = 4.
+
+        ptr_s = lltype.nullptr(rffi.LONGP.TO)
+
+        res = api._PyArray_SimpleNewFromData(0, ptr_s, 15, ptr_a)
+        assert res.get_scalar_value().real == 3.
+        assert res.get_scalar_value().imag == 4.
+
+class AppTestCNumber(AppTestCpythonExtensionBase):
+    def test_ndarray_object_c(self):
+        mod = self.import_extension('foo', [
+                ("test_simplenew", "METH_NOARGS",
+                '''
+                npy_intp dims[2] ={2, 3};
+                PyObject * obj = PyArray_SimpleNew(2, dims, 11);
+                return obj;
+                '''
+                ),
+                ("test_fill", "METH_NOARGS",
+                '''
+                npy_intp dims[2] ={2, 3};
+                PyObject * obj = PyArray_SimpleNew(2, dims, 1);
+                PyArray_FILLWBYTE(obj, 42);
+                return obj;
+                '''
+                ),
+                ("test_copy", "METH_NOARGS",
+                '''
+                npy_intp dims1[2] ={2, 3};
+                npy_intp dims2[2] ={3, 2};
+                PyObject * obj1 = PyArray_ZEROS(2, dims1, 11, 0);
+                PyObject * obj2 = PyArray_ZEROS(2, dims2, 11, 0);
+                PyArray_FILLWBYTE(obj2, 42);
+                PyArray_CopyInto(obj2, obj1);
+                Py_DECREF(obj1);
+                return obj2;
+                '''
+                ),
+                ("test_FromAny", "METH_NOARGS",
+                '''
+                npy_intp dims[2] ={2, 3};
+                PyObject * obj1 = PyArray_SimpleNew(2, dims, 1);
+                PyArray_FILLWBYTE(obj1, 42);
+                PyObject * obj2 = _PyArray_FromAny(obj1, NULL, 0, 0, 0, NULL);
+                Py_DECREF(obj1);
+                return obj2;
+                '''
+                ),
+                 ("test_FromObject", "METH_NOARGS",
+                '''
+                npy_intp dims[2] ={2, 3};
+                PyObject * obj1 = PyArray_SimpleNew(2, dims, 1);
+                PyArray_FILLWBYTE(obj1, 42);
+                PyObject * obj2 = _PyArray_FromObject(obj1, 12, 0, 0);
+                Py_DECREF(obj1);
+                return obj2;
+                '''
+                ),
+                ], prologue='#include <numpy/arrayobject.h>')
+        arr = mod.test_simplenew()
+        assert arr.shape == (2, 3)
+        assert arr.dtype.num == 11 #float32 dtype
+        arr = mod.test_fill()
+        assert arr.shape == (2, 3)
+        assert arr.dtype.num == 1 #int8 dtype
+        assert (arr == 42).all()
+        arr = mod.test_copy()
+        assert (arr == 0).all()
+        #Make sure these work without errors
+        arr = mod.test_FromAny()
+        arr = mod.test_FromObject()

File pypy/module/cpyext/test/test_number.py

-from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.interpreter.error import OperationError
+from rpython.rtyper.lltypesystem import lltype
 from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext import sequence
+from pypy.module.cpyext.pyobject import PyObjectP, from_ref, make_ref, Py_DecRef
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 
 class TestIterator(BaseApiTest):
     def test_check(self, space, api):
         assert w_l is None
         api.PyErr_Clear()
 
+    def test_coerce(self, space, api):
+        w_obj1 = space.wrap(123)
+        w_obj2 = space.wrap(456.789)
+        pp1 = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        pp1[0] = make_ref(space, w_obj1)
+        pp2 = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        pp2[0] = make_ref(space, w_obj2)
+        assert api.PyNumber_Coerce(pp1, pp2) == 0
+        assert space.str_w(space.repr(from_ref(space, pp1[0]))) == '123.0'
+        assert space.str_w(space.repr(from_ref(space, pp2[0]))) == '456.789'
+        Py_DecRef(space, pp1[0])
+        Py_DecRef(space, pp2[0])
+        lltype.free(pp1, flavor='raw')
+        # Yes, decrement twice since we decoupled between w_obj* and pp*[0].
+        Py_DecRef(space, w_obj1)
+        Py_DecRef(space, w_obj2)
+        lltype.free(pp2, flavor='raw')
+
+    def test_number_coerce_ex(self, space, api):
+        pl = make_ref(space, space.wrap(123))
+        pf = make_ref(space, space.wrap(42.))
+        ppl = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        ppf = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        ppl[0] = pl
+        ppf[0] = pf
+
+        ret = api.PyNumber_CoerceEx(ppl, ppf)
+        assert ret == 0
+
+        w_res = from_ref(space, ppl[0])
+
+        assert api.PyFloat_Check(w_res)
+        assert space.unwrap(w_res) == 123.
+        Py_DecRef(space, pl)
+        Py_DecRef(space, pf)
+        Py_DecRef(space, ppl[0])
+        Py_DecRef(space, ppf[0])
+        lltype.free(ppl, flavor='raw')
+        lltype.free(ppf, flavor='raw')
+
     def test_numbermethods(self, space, api):
         assert "ab" == space.unwrap(
             api.PyNumber_Add(space.wrap("a"), space.wrap("b")))
             api.PyNumber_Power(space.wrap(3), space.wrap(2), space.wrap(5)))
         assert 9 == space.unwrap(
             api.PyNumber_InPlacePower(space.wrap(3), space.wrap(2), space.w_None))
+
+class AppTestCNumber(AppTestCpythonExtensionBase):
+    def test_app_coerce(self):
+        mod = self.import_extension('foo', [
+            ("test_fail", "METH_NOARGS",
+             '''
+                PyObject * hello = PyString_FromString("hello");
+                PyObject * float1 = PyFloat_FromDouble(1.0);
+                int retVal = PyNumber_Coerce(&hello, &float1);
+                Py_DECREF(hello);
+                Py_DECREF(float1);
+                return PyInt_FromLong(retVal);
+            '''),
+            ("test", "METH_NOARGS",
+             '''
+                PyObject * float1p = PyFloat_FromDouble(1.0);
+                PyObject * int3p   = PyInt_FromLong(3);
+                PyObject * tupl = PyTuple_New(2);
+                PyObject float1 = *float1p;
+                PyObject int3 = *int3p;
+                int retVal = PyNumber_CoerceEx(&int3p, &float1p);
+                if (retVal == 0)
+                {
+                    PyTuple_SET_ITEM(tupl, 0, int3p);
+                    PyTuple_SET_ITEM(tupl, 1, float1p);
+                }
+                Py_DECREF(&int3);
+                Py_DECREF(&float1);
+                Py_DECREF(int3p);
+                Py_DECREF(float1p);
+                return tupl;
+            ''')])
+        assert mod.test_fail() == -1
+        '''tupl = mod.test()
+        assert tupl[0] == 3.
+        assert tupl[1] == 1.
+        assert isinstance(tupl[0], float)'''

File pypy/module/cpyext/test/test_ztranslation.py

+from pypy.objspace.fake.checkmodule import checkmodule
+
+def test_cpyext_translates():
+    checkmodule('cpyext', '_ffi')

File pypy/module/micronumpy/arrayimpl/base.py

     def base(self):
         raise NotImplementedError
 
-    def create_iter(self, shape=None, backward_broadcast=False):
+    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
         raise NotImplementedError
 
 class BaseArrayIterator(object):

File pypy/module/micronumpy/arrayimpl/concrete.py

         return W_NDimArray.new_slice(space, self.start, strides,
                                      backstrides, shape, self, orig_arr)
 
+    def nonzero(self, space, index_type):
+        s = loop.count_all_true_concrete(self)
+        box = index_type.itemtype.box
+        nd = len(self.get_shape())
+        w_res = W_NDimArray.from_shape(space, [s, nd], index_type)
+        loop.nonzero(w_res, self, box)
+        w_res = w_res.implementation.swapaxes(space, w_res, 0, 1)
+        l_w = [w_res.descr_getitem(space, space.wrap(d)) for d in range(nd)]
+        return space.newtuple(l_w)
+
     def get_storage_as_int(self, space):
         return rffi.cast(lltype.Signed, self.storage) + self.start
 
         self.backstrides = backstrides
         self.storage = storage
 
-    def create_iter(self, shape=None, backward_broadcast=False):
-        if shape is None or \
-           support.product(shape) <= support.product(self.get_shape()):
+    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
+        if shape is not None and \
+                support.product(shape) > support.product(self.get_shape()):
+            r = calculate_broadcast_strides(self.get_strides(),
+                                            self.get_backstrides(),
+                                            self.get_shape(), shape, backward_broadcast)
+            return iter.MultiDimViewIterator(self, self.dtype, self.start, r[0], r[1], shape)
+
+        if not require_index:
             return iter.ConcreteArrayIterator(self)
-        r = calculate_broadcast_strides(self.get_strides(),
-                                        self.get_backstrides(),
-                                        self.get_shape(), shape, backward_broadcast)
-        return iter.MultiDimViewIterator(self, self.dtype, 0, r[0], r[1], shape)
+        else:
+            if len(self.get_shape()) == 1:
+                return iter.OneDimViewIterator(self, self.dtype, self.start,
+                        self.get_strides(), self.get_shape())
+            else:
+                return iter.MultiDimViewIterator(self, self.dtype, self.start,
+                        self.get_strides(), self.get_backstrides(), self.get_shape())
 
     def fill(self, box):
         self.dtype.fill(self.storage, box, 0, self.size)
     def fill(self, box):
         loop.fill(self, box.convert_to(self.dtype))
 
-    def create_iter(self, shape=None, backward_broadcast=False):
-        if shape is not None and shape != self.get_shape() and \
-           support.product(shape) > support.product(self.get_shape()):
+    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
+        if shape is not None and \
+                support.product(shape) > support.product(self.get_shape()):
             r = calculate_broadcast_strides(self.get_strides(),
                                             self.get_backstrides(),
                                             self.get_shape(), shape,

File pypy/module/micronumpy/arrayimpl/scalar.py

     def get_backstrides(self):
         return []
 
-    def create_iter(self, shape=None, backward_broadcast=False):
+    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
         return ScalarIterator(self)
 
     def get_scalar_value(self):
     def swapaxes(self, space, orig_array, axis1, axis2):
         raise Exception("should not be called")
 
+    def nonzero(self, space, index_type):
+        s = self.dtype.itemtype.bool(self.value)
+        w_res = W_NDimArray.from_shape(space, [s], index_type)
+        if s == 1:
+            w_res.implementation.setitem(0, index_type.itemtype.box(0)) 
+        return space.newtuple([w_res])
+
     def fill(self, w_value):
         self.value = w_value
 

File pypy/module/micronumpy/base.py

 
+from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import W_Root
 from rpython.tool.pairtype import extendabletype
 from pypy.module.micronumpy.support import calc_strides
 
 
 def convert_to_array(space, w_obj):
+    #XXX: This whole routine should very likely simply be array()
     from pypy.module.micronumpy.interp_numarray import array
     from pypy.module.micronumpy import interp_ufuncs
 
     if isinstance(w_obj, W_NDimArray):
         return w_obj
-    elif issequence_w(space, w_obj):
-        # Convert to array.
-        return array(space, w_obj, w_order=None)
     else:
-        # If it's a scalar
-        dtype = interp_ufuncs.find_dtype_for_scalar(space, w_obj)
-        return W_NDimArray.new_scalar(space, dtype, w_obj)
+        # Use __array__() method if it exists
+        w_array = space.lookup(w_obj, "__array__")
+        if w_array is not None:
+            w_result = space.get_and_call_function(w_array, w_obj)
+            if isinstance(w_result, W_NDimArray):
+                return w_result
+            else:
+                raise OperationError(space.w_ValueError, 
+                        space.wrap("object __array__ method not producing an array"))
+        elif issequence_w(space, w_obj):
+            # Convert to array.
+            return array(space, w_obj, w_order=None)
+        else:
+            # If it's a scalar
+            dtype = interp_ufuncs.find_dtype_for_scalar(space, w_obj)
+            return W_NDimArray.new_scalar(space, dtype, w_obj)

File pypy/module/micronumpy/compile.py

     def __init__(self, name):
         self.name = name
 
+    def lookup(self, name):
+        return self.getdictvalue(self, name)
+
 class FakeSpace(object):
     w_ValueError = W_TypeObject("ValueError")
     w_TypeError = W_TypeObject("TypeError")
                 return W_NDimArray
             return self.w_None
 
+    def lookup(self, w_obj, name):
+        w_type = self.type(w_obj)
+        return w_type.lookup(name)
+
     def gettypefor(self, w_obj):
         return None
 

File pypy/module/micronumpy/interp_dtype.py

                 self.dtypes_by_name[alias] = dtype
             self.dtypes_by_name[dtype.char] = dtype
 
-        self.dtypes_by_num = [dtype for dtype in
-                sorted(self.dtypes_by_num.values(), key=lambda dtype: dtype.num)
-                if dtype.num <= self.w_float64dtype.num]
-        assert len(self.dtypes_by_num) == self.w_float64dtype.num + 1
-
         typeinfo_full = {
             'LONGLONG': self.w_int64dtype,
             'SHORT': self.w_int16dtype,

File pypy/module/micronumpy/interp_flatiter.py

     def get_shape(self):
         return self.shape
 
-    def create_iter(self, shape=None, backward_broadcast=False):
+    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
         assert isinstance(self.base(), W_NDimArray)
         return self.base().create_iter()
 

File pypy/module/micronumpy/interp_numarray.py

 from pypy.module.micronumpy.base import W_NDimArray, convert_to_array,\
      ArrayArgumentException, issequence_w, wrap_impl
 from pypy.module.micronumpy import interp_dtype, interp_ufuncs, interp_boxes,\
-     interp_arrayops
+     interp_arrayops, iter
 from pypy.module.micronumpy.strides import find_shape_and_elems,\
      get_shape_from_iterable, to_coords, shape_agreement, \
      shape_agreement_multiple
         if idx.get_size() > self.get_size():
             raise OperationError(space.w_ValueError,
                                  space.wrap("index out of range for array"))
-        idx_iter = idx.create_iter()
-        size = loop.count_all_true_iter(idx_iter, idx.get_shape(), idx.get_dtype())
+        size = loop.count_all_true(idx)
         if size > val.get_size() and val.get_size() > 1:
             raise OperationError(space.w_ValueError, space.wrap("NumPy boolean array indexing assignment "
                                                                 "cannot assign %d input values to "
         s.append('])')
         return s.build()
 
-    def create_iter(self, shape=None, backward_broadcast=False):
+    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
         assert isinstance(self.implementation, BaseArrayImplementation)
         return self.implementation.create_iter(shape=shape,
-                                   backward_broadcast=backward_broadcast)
+                                   backward_broadcast=backward_broadcast,
+                                   require_index=require_index)
 
     def create_axis_iter(self, shape, dim, cum):
         return self.implementation.create_axis_iter(shape, dim, cum)
             return self
         return self.implementation.swapaxes(space, self, axis1, axis2)
 
+    def descr_nonzero(self, space):
+        index_type = interp_dtype.get_dtype_cache(space).w_int64dtype
+        return self.implementation.nonzero(space, index_type)
+
     def descr_tolist(self, space):
         if len(self.get_shape()) == 0:
             return self.get_scalar_value().item(space)
         raise OperationError(space.w_NotImplementedError, space.wrap(
             "non-int arg not supported"))
 
+    def descr___array__(self, space, w_dtype=None):
+        if not space.is_none(w_dtype):
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                "__array__(dtype) not implemented"))
+        # stub implementation of __array__()
+        return self
+
     def descr_array_iface(self, space):
         addr = self.implementation.get_storage_as_int(space)
         # will explode if it can't
 
     descr_conj = _unaryop_impl('conjugate')
 
-    def descr_nonzero(self, space):
+    def descr___nonzero__(self, space):
         if self.get_size() > 1:
             raise OperationError(space.w_ValueError, space.wrap(
                 "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"))
     __neg__ = interp2app(W_NDimArray.descr_neg),
     __abs__ = interp2app(W_NDimArray.descr_abs),
     __invert__ = interp2app(W_NDimArray.descr_invert),
-    __nonzero__ = interp2app(W_NDimArray.descr_nonzero),
+    __nonzero__ = interp2app(W_NDimArray.descr___nonzero__),
 
     __add__ = interp2app(W_NDimArray.descr_add),
     __sub__ = interp2app(W_NDimArray.descr_sub),
     compress = interp2app(W_NDimArray.descr_compress),
     repeat = interp2app(W_NDimArray.descr_repeat),
     swapaxes = interp2app(W_NDimArray.descr_swapaxes),
+    nonzero = interp2app(W_NDimArray.descr_nonzero),
     flat = GetSetProperty(W_NDimArray.descr_get_flatiter),
     item = interp2app(W_NDimArray.descr_item),
     real = GetSetProperty(W_NDimArray.descr_get_real,
     __reduce__ = interp2app(W_NDimArray.descr_reduce),
     __setstate__ = interp2app(W_NDimArray.descr_setstate),
     __array_finalize__ = interp2app(W_NDimArray.descr___array_finalize__),
+
+    __array__         = interp2app(W_NDimArray.descr___array__),
 )