[pypy-commit] pypy default: merge

l.diekmann noreply at buildbot.pypy.org
Sat Jan 28 14:01:05 CET 2012


Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: 
Changeset: r51909:51eb80cfd760
Date: 2012-01-28 14:00 +0100
http://bitbucket.org/pypy/pypy/changeset/51eb80cfd760/

Log:	merge

diff --git a/lib_pypy/numpypy/core/__init__.py b/lib_pypy/numpypy/core/__init__.py
--- a/lib_pypy/numpypy/core/__init__.py
+++ b/lib_pypy/numpypy/core/__init__.py
@@ -1,1 +1,2 @@
 from .fromnumeric import *
+from .numeric import *
diff --git a/lib_pypy/numpypy/core/_methods.py b/lib_pypy/numpypy/core/_methods.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/_methods.py
@@ -0,0 +1,98 @@
+# Array methods which are called by the both the C-code for the method
+# and the Python code for the NumPy-namespace function
+
+import _numpypy as mu
+um = mu
+#from numpypy.core import umath as um
+from numpypy.core.numeric import asanyarray
+
+def _amax(a, axis=None, out=None, skipna=False, keepdims=False):
+    return um.maximum.reduce(a, axis=axis,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _amin(a, axis=None, out=None, skipna=False, keepdims=False):
+    return um.minimum.reduce(a, axis=axis,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _sum(a, axis=None, dtype=None, out=None, skipna=False, keepdims=False):
+    return um.add.reduce(a, axis=axis, dtype=dtype,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _prod(a, axis=None, dtype=None, out=None, skipna=False, keepdims=False):
+    return um.multiply.reduce(a, axis=axis, dtype=dtype,
+                            out=out, skipna=skipna, keepdims=keepdims)
+
+def _mean(a, axis=None, dtype=None, out=None, skipna=False, keepdims=False):
+    arr = asanyarray(a)
+
+    # Upgrade bool, unsigned int, and int to float64
+    if dtype is None and arr.dtype.kind in ['b','u','i']:
+        ret = um.add.reduce(arr, axis=axis, dtype='f8',
+                            out=out, skipna=skipna, keepdims=keepdims)
+    else:
+        ret = um.add.reduce(arr, axis=axis, dtype=dtype,
+                            out=out, skipna=skipna, keepdims=keepdims)
+    rcount = mu.count_reduce_items(arr, axis=axis,
+                            skipna=skipna, keepdims=keepdims)
+    if isinstance(ret, mu.ndarray):
+        ret = um.true_divide(ret, rcount,
+                        casting='unsafe', subok=False)
+    else:
+        ret = ret / float(rcount)
+    return ret
+
+def _var(a, axis=None, dtype=None, out=None, ddof=0,
+                            skipna=False, keepdims=False):
+    arr = asanyarray(a)
+
+    # First compute the mean, saving 'rcount' for reuse later
+    if dtype is None and arr.dtype.kind in ['b','u','i']:
+        arrmean = um.add.reduce(arr, axis=axis, dtype='f8',
+                            skipna=skipna, keepdims=True)
+    else:
+        arrmean = um.add.reduce(arr, axis=axis, dtype=dtype,
+                            skipna=skipna, keepdims=True)
+    rcount = mu.count_reduce_items(arr, axis=axis,
+                            skipna=skipna, keepdims=True)
+    if isinstance(arrmean, mu.ndarray):
+        arrmean = um.true_divide(arrmean, rcount,
+                                  casting='unsafe', subok=False)
+    else:
+        arrmean = arrmean / float(rcount)
+
+    # arr - arrmean
+    x = arr - arrmean
+
+    # (arr - arrmean) ** 2
+    if arr.dtype.kind == 'c':
+        x = um.multiply(x, um.conjugate(x)).real
+    else:
+        x = um.multiply(x, x)
+
+    # add.reduce((arr - arrmean) ** 2, axis)
+    ret = um.add.reduce(x, axis=axis, dtype=dtype, out=out,
+                        skipna=skipna, keepdims=keepdims)
+
+    # add.reduce((arr - arrmean) ** 2, axis) / (n - ddof)
+    if not keepdims and isinstance(rcount, mu.ndarray):
+        rcount = rcount.squeeze(axis=axis)
+    rcount -= ddof
+    if isinstance(ret, mu.ndarray):
+        ret = um.true_divide(ret, rcount,
+                        casting='unsafe', subok=False)
+    else:
+        ret = ret / float(rcount)
+
+    return ret
+
+def _std(a, axis=None, dtype=None, out=None, ddof=0,
+                            skipna=False, keepdims=False):
+    ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
+                                skipna=skipna, keepdims=keepdims)
+
+    if isinstance(ret, mu.ndarray):
+        ret = um.sqrt(ret)
+    else:
+        ret = um.sqrt(ret)
+
+    return ret
diff --git a/lib_pypy/numpypy/core/arrayprint.py b/lib_pypy/numpypy/core/arrayprint.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/arrayprint.py
@@ -0,0 +1,789 @@
+"""Array printing function
+
+$Id: arrayprint.py,v 1.9 2005/09/13 13:58:44 teoliphant Exp $
+"""
+__all__ = ["array2string", "set_printoptions", "get_printoptions"]
+__docformat__ = 'restructuredtext'
+
+#
+# Written by Konrad Hinsen <hinsenk at ere.umontreal.ca>
+# last revision: 1996-3-13
+# modified by Jim Hugunin 1997-3-3 for repr's and str's (and other details)
+# and by Perry Greenfield 2000-4-1 for numarray
+# and by Travis Oliphant  2005-8-22 for numpy
+
+import sys
+import _numpypy as _nt
+from _numpypy import maximum, minimum, absolute, not_equal, isinf, isnan, isna
+#from _numpypy import format_longfloat, datetime_as_string, datetime_data
+from .fromnumeric import ravel
+
+
+def product(x, y): return x*y
+
+_summaryEdgeItems = 3     # repr N leading and trailing items of each dimension
+_summaryThreshold = 1000 # total items > triggers array summarization
+
+_float_output_precision = 8
+_float_output_suppress_small = False
+_line_width = 75
+_nan_str = 'nan'
+_inf_str = 'inf'
+_na_str = 'NA'
+_formatter = None  # formatting function for array elements
+
+if sys.version_info[0] >= 3:
+    from functools import reduce
+
+def set_printoptions(precision=None, threshold=None, edgeitems=None,
+                     linewidth=None, suppress=None,
+                     nanstr=None, infstr=None, nastr=None,
+                     formatter=None):
+    """
+    Set printing options.
+
+    These options determine the way floating point numbers, arrays and
+    other NumPy objects are displayed.
+
+    Parameters
+    ----------
+    precision : int, optional
+        Number of digits of precision for floating point output (default 8).
+    threshold : int, optional
+        Total number of array elements which trigger summarization
+        rather than full repr (default 1000).
+    edgeitems : int, optional
+        Number of array items in summary at beginning and end of
+        each dimension (default 3).
+    linewidth : int, optional
+        The number of characters per line for the purpose of inserting
+        line breaks (default 75).
+    suppress : bool, optional
+        Whether or not suppress printing of small floating point values
+        using scientific notation (default False).
+    nanstr : str, optional
+        String representation of floating point not-a-number (default nan).
+    infstr : str, optional
+        String representation of floating point infinity (default inf).
+    nastr : str, optional
+        String representation of NA missing value (default NA).
+    formatter : dict of callables, optional
+        If not None, the keys should indicate the type(s) that the respective
+        formatting function applies to.  Callables should return a string.
+        Types that are not specified (by their corresponding keys) are handled
+        by the default formatters.  Individual types for which a formatter
+        can be set are::
+
+            - 'bool'
+            - 'int'
+            - 'timedelta' : a `numpy.timedelta64`
+            - 'datetime' : a `numpy.datetime64`
+            - 'float'
+            - 'longfloat' : 128-bit floats
+            - 'complexfloat'
+            - 'longcomplexfloat' : composed of two 128-bit floats
+            - 'numpy_str' : types `numpy.string_` and `numpy.unicode_`
+            - 'str' : all other strings
+
+        Other keys that can be used to set a group of types at once are::
+
+            - 'all' : sets all types
+            - 'int_kind' : sets 'int'
+            - 'float_kind' : sets 'float' and 'longfloat'
+            - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
+            - 'str_kind' : sets 'str' and 'numpystr'
+
+    See Also
+    --------
+    get_printoptions, set_string_function, array2string
+
+    Notes
+    -----
+    `formatter` is always reset with a call to `set_printoptions`.
+
+    Examples
+    --------
+    Floating point precision can be set:
+
+    >>> np.set_printoptions(precision=4)
+    >>> print np.array([1.123456789])
+    [ 1.1235]
+
+    Long arrays can be summarised:
+
+    >>> np.set_printoptions(threshold=5)
+    >>> print np.arange(10)
+    [0 1 2 ..., 7 8 9]
+
+    Small results can be suppressed:
+
+    >>> eps = np.finfo(float).eps
+    >>> x = np.arange(4.)
+    >>> x**2 - (x + eps)**2
+    array([ -4.9304e-32,  -4.4409e-16,   0.0000e+00,   0.0000e+00])
+    >>> np.set_printoptions(suppress=True)
+    >>> x**2 - (x + eps)**2
+    array([-0., -0.,  0.,  0.])
+
+    A custom formatter can be used to display array elements as desired:
+
+    >>> np.set_printoptions(formatter={'all':lambda x: 'int: '+str(-x)})
+    >>> x = np.arange(3)
+    >>> x
+    array([int: 0, int: -1, int: -2])
+    >>> np.set_printoptions()  # formatter gets reset
+    >>> x
+    array([0, 1, 2])
+
+    To put back the default options, you can use:
+
+    >>> np.set_printoptions(edgeitems=3,infstr='inf',
+    ... linewidth=75, nanstr='nan', precision=8,
+    ... suppress=False, threshold=1000, formatter=None)
+    """
+
+    global _summaryThreshold, _summaryEdgeItems, _float_output_precision, \
+           _line_width, _float_output_suppress_small, _nan_str, _inf_str, \
+           _na_str, _formatter
+    if linewidth is not None:
+        _line_width = linewidth
+    if threshold is not None:
+        _summaryThreshold = threshold
+    if edgeitems is not None:
+        _summaryEdgeItems = edgeitems
+    if precision is not None:
+        _float_output_precision = precision
+    if suppress is not None:
+        _float_output_suppress_small = not not suppress
+    if nanstr is not None:
+        _nan_str = nanstr
+    if infstr is not None:
+        _inf_str = infstr
+    if nastr is not None:
+        _na_str = nastr
+    _formatter = formatter
+
+def get_printoptions():
+    """
+    Return the current print options.
+
+    Returns
+    -------
+    print_opts : dict
+        Dictionary of current print options with keys
+
+          - precision : int
+          - threshold : int
+          - edgeitems : int
+          - linewidth : int
+          - suppress : bool
+          - nanstr : str
+          - infstr : str
+          - formatter : dict of callables
+
+        For a full description of these options, see `set_printoptions`.
+
+    See Also
+    --------
+    set_printoptions, set_string_function
+
+    """
+    d = dict(precision=_float_output_precision,
+             threshold=_summaryThreshold,
+             edgeitems=_summaryEdgeItems,
+             linewidth=_line_width,
+             suppress=_float_output_suppress_small,
+             nanstr=_nan_str,
+             infstr=_inf_str,
+             nastr=_na_str,
+             formatter=_formatter)
+    return d
+
+def _leading_trailing(a):
+    import numeric as _nc
+    if a.ndim == 1:
+        if len(a) > 2*_summaryEdgeItems:
+            b = _nc.concatenate((a[:_summaryEdgeItems],
+                                     a[-_summaryEdgeItems:]))
+        else:
+            b = a
+    else:
+        if len(a) > 2*_summaryEdgeItems:
+            l = [_leading_trailing(a[i]) for i in range(
+                min(len(a), _summaryEdgeItems))]
+            l.extend([_leading_trailing(a[-i]) for i in range(
+                min(len(a), _summaryEdgeItems),0,-1)])
+        else:
+            l = [_leading_trailing(a[i]) for i in range(0, len(a))]
+        b = _nc.concatenate(tuple(l))
+    return b
+
+def _boolFormatter(x):
+    if isna(x):
+        return str(x).replace('NA', _na_str, 1)
+    elif x:
+        return ' True'
+    else:
+        return 'False'
+
+
+def repr_format(x):
+    if isna(x):
+        return str(x).replace('NA', _na_str, 1)
+    else:
+        return repr(x)
+
+def _array2string(a, max_line_width, precision, suppress_small, separator=' ',
+                  prefix="", formatter=None):
+
+    if max_line_width is None:
+        max_line_width = _line_width
+
+    if precision is None:
+        precision = _float_output_precision
+
+    if suppress_small is None:
+        suppress_small = _float_output_suppress_small
+
+    if formatter is None:
+        formatter = _formatter
+
+    if a.size > _summaryThreshold:
+        summary_insert = "..., "
+        data = _leading_trailing(a)
+    else:
+        summary_insert = ""
+        data = ravel(a)
+
+    formatdict = {'bool' : _boolFormatter,
+                  'int' : IntegerFormat(data),
+                  'float' : FloatFormat(data, precision, suppress_small),
+                  'longfloat' : LongFloatFormat(precision),
+                  #'complexfloat' : ComplexFormat(data, precision,
+                  #                               suppress_small),
+                  #'longcomplexfloat' : LongComplexFormat(precision),
+                  #'datetime' : DatetimeFormat(data),
+                  #'timedelta' : TimedeltaFormat(data),
+                  'numpystr' : repr_format,
+                  'str' : str}
+
+    if formatter is not None:
+        fkeys = [k for k in formatter.keys() if formatter[k] is not None]
+        if 'all' in fkeys:
+            for key in formatdict.keys():
+                formatdict[key] = formatter['all']
+        if 'int_kind' in fkeys:
+            for key in ['int']:
+                formatdict[key] = formatter['int_kind']
+        if 'float_kind' in fkeys:
+            for key in ['float', 'longfloat']:
+                formatdict[key] = formatter['float_kind']
+        if 'complex_kind' in fkeys:
+            for key in ['complexfloat', 'longcomplexfloat']:
+                formatdict[key] = formatter['complex_kind']
+        if 'str_kind' in fkeys:
+            for key in ['numpystr', 'str']:
+                formatdict[key] = formatter['str_kind']
+        for key in formatdict.keys():
+            if key in fkeys:
+                formatdict[key] = formatter[key]
+
+    try:
+        format_function = a._format
+        msg = "The `_format` attribute is deprecated in Numpy 2.0 and " \
+              "will be removed in 2.1. Use the `formatter` kw instead."
+        import warnings
+        warnings.warn(msg, DeprecationWarning)
+    except AttributeError:
+        # find the right formatting function for the array
+        dtypeobj = a.dtype.type
+        if issubclass(dtypeobj, _nt.bool_):
+            format_function = formatdict['bool']
+        elif issubclass(dtypeobj, _nt.integer):
+            #if issubclass(dtypeobj, _nt.timedelta64):
+            #    format_function = formatdict['timedelta']
+            #else:
+            format_function = formatdict['int']
+        elif issubclass(dtypeobj, _nt.floating):
+            #if issubclass(dtypeobj, _nt.longfloat):
+            #    format_function = formatdict['longfloat']
+            #else:
+            format_function = formatdict['float']
+        elif issubclass(dtypeobj, _nt.complexfloating):
+            if issubclass(dtypeobj, _nt.clongfloat):
+                format_function = formatdict['longcomplexfloat']
+            else:
+                format_function = formatdict['complexfloat']
+        elif issubclass(dtypeobj, (_nt.unicode_, _nt.string_)):
+            format_function = formatdict['numpystr']
+        elif issubclass(dtypeobj, _nt.datetime64):
+            format_function = formatdict['datetime']
+        else:
+            format_function = formatdict['str']
+
+    # skip over "["
+    next_line_prefix = " "
+    # skip over array(
+    next_line_prefix += " "*len(prefix)
+
+    lst = _formatArray(a, format_function, len(a.shape), max_line_width,
+                       next_line_prefix, separator,
+                       _summaryEdgeItems, summary_insert)[:-1]
+    return lst
+
+def _convert_arrays(obj):
+    import numeric as _nc
+    newtup = []
+    for k in obj:
+        if isinstance(k, _nc.ndarray):
+            k = k.tolist()
+        elif isinstance(k, tuple):
+            k = _convert_arrays(k)
+        newtup.append(k)
+    return tuple(newtup)
+
+
+def array2string(a, max_line_width=None, precision=None,
+                 suppress_small=None, separator=' ', prefix="",
+                 style=repr, formatter=None):
+    """
+    Return a string representation of an array.
+
+    Parameters
+    ----------
+    a : ndarray
+        Input array.
+    max_line_width : int, optional
+        The maximum number of columns the string should span. Newline
+        characters splits the string appropriately after array elements.
+    precision : int, optional
+        Floating point precision. Default is the current printing
+        precision (usually 8), which can be altered using `set_printoptions`.
+    suppress_small : bool, optional
+        Represent very small numbers as zero. A number is "very small" if it
+        is smaller than the current printing precision.
+    separator : str, optional
+        Inserted between elements.
+    prefix : str, optional
+        An array is typically printed as::
+
+          'prefix(' + array2string(a) + ')'
+
+        The length of the prefix string is used to align the
+        output correctly.
+    style : function, optional
+        A function that accepts an ndarray and returns a string.  Used only
+        when the shape of `a` is equal to ``()``, i.e. for 0-D arrays.
+    formatter : dict of callables, optional
+        If not None, the keys should indicate the type(s) that the respective
+        formatting function applies to.  Callables should return a string.
+        Types that are not specified (by their corresponding keys) are handled
+        by the default formatters.  Individual types for which a formatter
+        can be set are::
+
+            - 'bool'
+            - 'int'
+            - 'timedelta' : a `numpy.timedelta64`
+            - 'datetime' : a `numpy.datetime64`
+            - 'float'
+            - 'longfloat' : 128-bit floats
+            - 'complexfloat'
+            - 'longcomplexfloat' : composed of two 128-bit floats
+            - 'numpy_str' : types `numpy.string_` and `numpy.unicode_`
+            - 'str' : all other strings
+
+        Other keys that can be used to set a group of types at once are::
+
+            - 'all' : sets all types
+            - 'int_kind' : sets 'int'
+            - 'float_kind' : sets 'float' and 'longfloat'
+            - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
+            - 'str_kind' : sets 'str' and 'numpystr'
+
+    Returns
+    -------
+    array_str : str
+        String representation of the array.
+
+    Raises
+    ------
+    TypeError : if a callable in `formatter` does not return a string.
+
+    See Also
+    --------
+    array_str, array_repr, set_printoptions, get_printoptions
+
+    Notes
+    -----
+    If a formatter is specified for a certain type, the `precision` keyword is
+    ignored for that type.
+
+    Examples
+    --------
+    >>> x = np.array([1e-16,1,2,3])
+    >>> print np.array2string(x, precision=2, separator=',',
+    ...                       suppress_small=True)
+    [ 0., 1., 2., 3.]
+
+    >>> x  = np.arange(3.)
+    >>> np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x})
+    '[0.00 1.00 2.00]'
+
+    >>> x  = np.arange(3)
+    >>> np.array2string(x, formatter={'int':lambda x: hex(x)})
+    '[0x0L 0x1L 0x2L]'
+
+    """
+
+    if a.shape == ():
+        x = a.item()
+        if isna(x):
+            lst = str(x).replace('NA', _na_str, 1)
+        else:
+            try:
+                lst = a._format(x)
+                msg = "The `_format` attribute is deprecated in Numpy " \
+                      "2.0 and will be removed in 2.1. Use the " \
+                      "`formatter` kw instead."
+                import warnings
+                warnings.warn(msg, DeprecationWarning)
+            except AttributeError:
+                if isinstance(x, tuple):
+                    x = _convert_arrays(x)
+                lst = style(x)
+    elif reduce(product, a.shape) == 0:
+        # treat as a null array if any of shape elements == 0
+        lst = "[]"
+    else:
+        lst = _array2string(a, max_line_width, precision, suppress_small,
+                            separator, prefix, formatter=formatter)
+    return lst
+
+def _extendLine(s, line, word, max_line_len, next_line_prefix):
+    if len(line.rstrip()) + len(word.rstrip()) >= max_line_len:
+        s += line.rstrip() + "\n"
+        line = next_line_prefix
+    line += word
+    return s, line
+
+
+def _formatArray(a, format_function, rank, max_line_len,
+                 next_line_prefix, separator, edge_items, summary_insert):
+    """formatArray is designed for two modes of operation:
+
+    1. Full output
+
+    2. Summarized output
+
+    """
+    if rank == 0:
+        obj = a.item()
+        if isinstance(obj, tuple):
+            obj = _convert_arrays(obj)
+        return str(obj)
+
+    if summary_insert and 2*edge_items < len(a):
+        leading_items, trailing_items, summary_insert1 = \
+                       edge_items, edge_items, summary_insert
+    else:
+        leading_items, trailing_items, summary_insert1 = 0, len(a), ""
+
+    if rank == 1:
+        s = ""
+        line = next_line_prefix
+        for i in xrange(leading_items):
+            word = format_function(a[i]) + separator
+            s, line = _extendLine(s, line, word, max_line_len, next_line_prefix)
+
+        if summary_insert1:
+            s, line = _extendLine(s, line, summary_insert1, max_line_len, next_line_prefix)
+
+        for i in xrange(trailing_items, 1, -1):
+            word = format_function(a[-i]) + separator
+            s, line = _extendLine(s, line, word, max_line_len, next_line_prefix)
+
+        word = format_function(a[-1])
+        s, line = _extendLine(s, line, word, max_line_len, next_line_prefix)
+        s += line + "]\n"
+        s = '[' + s[len(next_line_prefix):]
+    else:
+        s = '['
+        sep = separator.rstrip()
+        for i in xrange(leading_items):
+            if i > 0:
+                s += next_line_prefix
+            s += _formatArray(a[i], format_function, rank-1, max_line_len,
+                              " " + next_line_prefix, separator, edge_items,
+                              summary_insert)
+            s = s.rstrip() + sep.rstrip() + '\n'*max(rank-1,1)
+
+        if summary_insert1:
+            s += next_line_prefix + summary_insert1 + "\n"
+
+        for i in xrange(trailing_items, 1, -1):
+            if leading_items or i != trailing_items:
+                s += next_line_prefix
+            s += _formatArray(a[-i], format_function, rank-1, max_line_len,
+                              " " + next_line_prefix, separator, edge_items,
+                              summary_insert)
+            s = s.rstrip() + sep.rstrip() + '\n'*max(rank-1,1)
+        if leading_items or trailing_items > 1:
+            s += next_line_prefix
+        s += _formatArray(a[-1], format_function, rank-1, max_line_len,
+                          " " + next_line_prefix, separator, edge_items,
+                          summary_insert).rstrip()+']\n'
+    return s
+
+class FloatFormat(object):
+    def __init__(self, data, precision, suppress_small, sign=False):
+        self.precision = precision
+        self.suppress_small = suppress_small
+        self.sign = sign
+        self.exp_format = False
+        self.large_exponent = False
+        self.max_str_len = 0
+        #try:
+        self.fillFormat(data)
+        #except (TypeError, NotImplementedError):
+            # if reduce(data) fails, this instance will not be called, just
+            # instantiated in formatdict.
+            #pass
+
+    def fillFormat(self, data):
+        import numeric as _nc
+        # XXX pypy unimplemented
+        #errstate = _nc.seterr(all='ignore')
+        try:
+            special = isnan(data) | isinf(data) | isna(data)
+            special[isna(data)] = False
+            valid = not_equal(data, 0) & ~special
+            valid[isna(data)] = False
+            non_zero = absolute(data.compress(valid))
+            if len(non_zero) == 0:
+                max_val = 0.
+                min_val = 0.
+            else:
+                max_val = maximum.reduce(non_zero, skipna=True)
+                min_val = minimum.reduce(non_zero, skipna=True)
+                if max_val >= 1.e8:
+                    self.exp_format = True
+                if not self.suppress_small and (min_val < 0.0001
+                                           or max_val/min_val > 1000.):
+                    self.exp_format = True
+        finally:
+            pass
+            # XXX pypy unimplemented
+            #_nc.seterr(**errstate)
+
+        if self.exp_format:
+            self.large_exponent = 0 < min_val < 1e-99 or max_val >= 1e100
+            self.max_str_len = 8 + self.precision
+            if self.large_exponent:
+                self.max_str_len += 1
+            if self.sign:
+                format = '%+'
+            else:
+                format = '%'
+            format = format + '%d.%de' % (self.max_str_len, self.precision)
+        else:
+            format = '%%.%df' % (self.precision,)
+            if len(non_zero):
+                precision = max([_digits(x, self.precision, format)
+                                 for x in non_zero])
+            else:
+                precision = 0
+            precision = min(self.precision, precision)
+            self.max_str_len = len(str(int(max_val))) + precision + 2
+            if special.any():
+                self.max_str_len = max(self.max_str_len,
+                                       len(_nan_str),
+                                       len(_inf_str)+1,
+                                       len(_na_str))
+            if self.sign:
+                format = '%#+'
+            else:
+                format = '%#'
+            format = format + '%d.%df' % (self.max_str_len, precision)
+
+        self.special_fmt = '%%%ds' % (self.max_str_len,)
+        self.format = format
+
+    def __call__(self, x, strip_zeros=True):
+        import numeric as _nc
+        #err = _nc.seterr(invalid='ignore')
+        try:
+            if isna(x):
+                return self.special_fmt % (str(x).replace('NA', _na_str, 1),)
+            elif isnan(x):
+                if self.sign:
+                    return self.special_fmt % ('+' + _nan_str,)
+                else:
+                    return self.special_fmt % (_nan_str,)
+            elif isinf(x):
+                if x > 0:
+                    if self.sign:
+                        return self.special_fmt % ('+' + _inf_str,)
+                    else:
+                        return self.special_fmt % (_inf_str,)
+                else:
+                    return self.special_fmt % ('-' + _inf_str,)
+        finally:
+            pass
+            #_nc.seterr(**err)
+
+        s = self.format % x
+        if self.large_exponent:
+            # 3-digit exponent
+            expsign = s[-3]
+            if expsign == '+' or expsign == '-':
+                s = s[1:-2] + '0' + s[-2:]
+        elif self.exp_format:
+            # 2-digit exponent
+            if s[-3] == '0':
+                s = ' ' + s[:-3] + s[-2:]
+        elif strip_zeros:
+            z = s.rstrip('0')
+            s = z + ' '*(len(s)-len(z))
+        return s
+
+
+def _digits(x, precision, format):
+    s = format % x
+    z = s.rstrip('0')
+    return precision - len(s) + len(z)
+
+
+_MAXINT = sys.maxint
+_MININT = -sys.maxint-1
+class IntegerFormat(object):
+    def __init__(self, data):
+        try:
+            max_str_len = max(len(str(maximum.reduce(data, skipna=True))),
+                              len(str(minimum.reduce(data, skipna=True))))
+            self.format = '%' + str(max_str_len) + 'd'
+        except TypeError, NotImplementedError:
+            # if reduce(data) fails, this instance will not be called, just
+            # instantiated in formatdict.
+            pass
+        except ValueError:
+            # this occurs when everything is NA
+            pass
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        elif _MININT < x < _MAXINT:
+            return self.format % x
+        else:
+            return "%s" % x
+
+class LongFloatFormat(object):
+    # XXX Have to add something to determine the width to use a la FloatFormat
+    # Right now, things won't line up properly
+    def __init__(self, precision, sign=False):
+        self.precision = precision
+        self.sign = sign
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        elif isnan(x):
+            if self.sign:
+                return '+' + _nan_str
+            else:
+                return ' ' + _nan_str
+        elif isinf(x):
+            if x > 0:
+                if self.sign:
+                    return '+' + _inf_str
+                else:
+                    return ' ' + _inf_str
+            else:
+                return '-' + _inf_str
+        elif x >= 0:
+            if self.sign:
+                return '+' + format_longfloat(x, self.precision)
+            else:
+                return ' ' + format_longfloat(x, self.precision)
+        else:
+            return format_longfloat(x, self.precision)
+
+
+class LongComplexFormat(object):
+    def __init__(self, precision):
+        self.real_format = LongFloatFormat(precision)
+        self.imag_format = LongFloatFormat(precision, sign=True)
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            r = self.real_format(x.real)
+            i = self.imag_format(x.imag)
+            return r + i + 'j'
+
+
+class ComplexFormat(object):
+    def __init__(self, x, precision, suppress_small):
+        self.real_format = FloatFormat(x.real, precision, suppress_small)
+        self.imag_format = FloatFormat(x.imag, precision, suppress_small,
+                                       sign=True)
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            r = self.real_format(x.real, strip_zeros=False)
+            i = self.imag_format(x.imag, strip_zeros=False)
+            if not self.imag_format.exp_format:
+                z = i.rstrip('0')
+                i = z + 'j' + ' '*(len(i)-len(z))
+            else:
+                i = i + 'j'
+            return r + i
+
+class DatetimeFormat(object):
+    def __init__(self, x, unit=None,
+                timezone=None, casting='same_kind'):
+        # Get the unit from the dtype
+        if unit is None:
+            if x.dtype.kind == 'M':
+                unit = datetime_data(x.dtype)[0]
+            else:
+                unit = 's'
+
+        # If timezone is default, make it 'local' or 'UTC' based on the unit
+        if timezone is None:
+            # Date units -> UTC, time units -> local
+            if unit in ('Y', 'M', 'W', 'D'):
+                self.timezone = 'UTC'
+            else:
+                self.timezone = 'local'
+        else:
+            self.timezone = timezone
+        self.unit = unit
+        self.casting = casting
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            return "'%s'" % datetime_as_string(x,
+                                        unit=self.unit,
+                                        timezone=self.timezone,
+                                        casting=self.casting)
+
+class TimedeltaFormat(object):
+    def __init__(self, data):
+        if data.dtype.kind == 'm':
+            v = data.view('i8')
+            max_str_len = max(len(str(maximum.reduce(v))),
+                              len(str(minimum.reduce(v))))
+            self.format = '%' + str(max_str_len) + 'd'
+
+    def __call__(self, x):
+        if isna(x):
+            return str(x).replace('NA', _na_str, 1)
+        else:
+            return self.format % x.astype('i8')
+
diff --git a/lib_pypy/numpypy/core/fromnumeric.py b/lib_pypy/numpypy/core/fromnumeric.py
--- a/lib_pypy/numpypy/core/fromnumeric.py
+++ b/lib_pypy/numpypy/core/fromnumeric.py
@@ -30,7 +30,7 @@
            'rank', 'size', 'around', 'round_', 'mean', 'std', 'var', 'squeeze',
            'amax', 'amin',
           ]
-          
+
 def take(a, indices, axis=None, out=None, mode='raise'):
     """
     Take elements from an array along an axis.
@@ -1054,8 +1054,9 @@
     array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
 
     """
-    raise NotImplementedError('Waiting on interp level method')
-
+    if not hasattr(a, 'ravel'):
+        a = numpypy.array(a)
+    return a.ravel(order=order)
 
 def nonzero(a):
     """
@@ -2324,13 +2325,12 @@
     0.44999999925552653
 
     """
-    assert axis is None
     assert dtype is None
     assert out is None
     assert ddof == 0
     if not hasattr(a, "std"):
         a = numpypy.array(a)
-    return a.std()
+    return a.std(axis=axis)
 
 
 def var(a, axis=None, dtype=None, out=None, ddof=0):
@@ -2421,10 +2421,9 @@
     0.20250000000000001
 
     """
-    assert axis is None
     assert dtype is None
     assert out is None
     assert ddof == 0
     if not hasattr(a, "var"):
         a = numpypy.array(a)
-    return a.var()
+    return a.var(axis=axis)
diff --git a/lib_pypy/numpypy/core/numeric.py b/lib_pypy/numpypy/core/numeric.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/numeric.py
@@ -0,0 +1,311 @@
+
+from _numpypy import array, ndarray, int_, float_ #, complex_# , longlong
+from _numpypy import concatenate
+import sys
+import _numpypy as multiarray # ARGH
+from numpypy.core.arrayprint import array2string
+
+
+
+def asanyarray(a, dtype=None, order=None, maskna=None, ownmaskna=False):
+    """
+    Convert the input to an ndarray, but pass ndarray subclasses through.
+
+    Parameters
+    ----------
+    a : array_like
+        Input data, in any form that can be converted to an array.  This
+        includes scalars, lists, lists of tuples, tuples, tuples of tuples,
+        tuples of lists, and ndarrays.
+    dtype : data-type, optional
+        By default, the data-type is inferred from the input data.
+    order : {'C', 'F'}, optional
+        Whether to use row-major ('C') or column-major ('F') memory
+        representation.  Defaults to 'C'.
+   maskna : bool or None, optional
+        If this is set to True, it forces the array to have an NA mask.
+        If this is set to False, it forces the array to not have an NA
+        mask.
+    ownmaskna : bool, optional
+        If this is set to True, forces the array to have a mask which
+        it owns.
+
+    Returns
+    -------
+    out : ndarray or an ndarray subclass
+        Array interpretation of `a`.  If `a` is an ndarray or a subclass
+        of ndarray, it is returned as-is and no copy is performed.
+
+    See Also
+    --------
+    asarray : Similar function which always returns ndarrays.
+    ascontiguousarray : Convert input to a contiguous array.
+    asfarray : Convert input to a floating point ndarray.
+    asfortranarray : Convert input to an ndarray with column-major
+                     memory order.
+    asarray_chkfinite : Similar function which checks input for NaNs and
+                        Infs.
+    fromiter : Create an array from an iterator.
+    fromfunction : Construct an array by executing a function on grid
+                   positions.
+
+    Examples
+    --------
+    Convert a list into an array:
+
+    >>> a = [1, 2]
+    >>> np.asanyarray(a)
+    array([1, 2])
+
+    Instances of `ndarray` subclasses are passed through as-is:
+
+    >>> a = np.matrix([1, 2])
+    >>> np.asanyarray(a) is a
+    True
+
+    """
+    return array(a, dtype, copy=False, order=order, subok=True,
+                                maskna=maskna, ownmaskna=ownmaskna)
+
+def base_repr(number, base=2, padding=0):
+    """
+    Return a string representation of a number in the given base system.
+
+    Parameters
+    ----------
+    number : int
+        The value to convert. Only positive values are handled.
+    base : int, optional
+        Convert `number` to the `base` number system. The valid range is 2-36,
+        the default value is 2.
+    padding : int, optional
+        Number of zeros padded on the left. Default is 0 (no padding).
+
+    Returns
+    -------
+    out : str
+        String representation of `number` in `base` system.
+
+    See Also
+    --------
+    binary_repr : Faster version of `base_repr` for base 2.
+
+    Examples
+    --------
+    >>> np.base_repr(5)
+    '101'
+    >>> np.base_repr(6, 5)
+    '11'
+    >>> np.base_repr(7, base=5, padding=3)
+    '00012'
+
+    >>> np.base_repr(10, base=16)
+    'A'
+    >>> np.base_repr(32, base=16)
+    '20'
+
+    """
+    digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+    if base > len(digits):
+        raise ValueError("Bases greater than 36 not handled in base_repr.")
+
+    num = abs(number)
+    res = []
+    while num:
+        res.append(digits[num % base])
+        num //= base
+    if padding:
+        res.append('0' * padding)
+    if number < 0:
+        res.append('-')
+    return ''.join(reversed(res or '0'))
+
+_typelessdata = [int_, float_]#, complex_]
+# XXX
+#if issubclass(intc, int):
+#    _typelessdata.append(intc)
+
+#if issubclass(longlong, int):
+#    _typelessdata.append(longlong)
+
+def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
+    """
+    Return the string representation of an array.
+
+    Parameters
+    ----------
+    arr : ndarray
+        Input array.
+    max_line_width : int, optional
+        The maximum number of columns the string should span. Newline
+        characters split the string appropriately after array elements.
+    precision : int, optional
+        Floating point precision. Default is the current printing precision
+        (usually 8), which can be altered using `set_printoptions`.
+    suppress_small : bool, optional
+        Represent very small numbers as zero, default is False. Very small
+        is defined by `precision`, if the precision is 8 then
+        numbers smaller than 5e-9 are represented as zero.
+
+    Returns
+    -------
+    string : str
+      The string representation of an array.
+
+    See Also
+    --------
+    array_str, array2string, set_printoptions
+
+    Examples
+    --------
+    >>> np.array_repr(np.array([1,2]))
+    'array([1, 2])'
+    >>> np.array_repr(np.ma.array([0.]))
+    'MaskedArray([ 0.])'
+    >>> np.array_repr(np.array([], np.int32))
+    'array([], dtype=int32)'
+
+    >>> x = np.array([1e-6, 4e-7, 2, 3])
+    >>> np.array_repr(x, precision=6, suppress_small=True)
+    'array([ 0.000001,  0.      ,  2.      ,  3.      ])'
+
+    """
+    if arr.size > 0 or arr.shape==(0,):
+        lst = array2string(arr, max_line_width, precision, suppress_small,
+                           ', ', "array(")
+    else: # show zero-length shape unless it is (0,)
+        lst = "[], shape=%s" % (repr(arr.shape),)
+
+    if arr.__class__ is not ndarray:
+        cName= arr.__class__.__name__
+    else:
+        cName = "array"
+
+    skipdtype = (arr.dtype.type in _typelessdata) and arr.size > 0
+
+    # XXX pypy lacks support
+    if 0 and arr.flags.maskna:
+        whichna = isna(arr)
+        # If nothing is NA, explicitly signal the NA-mask
+        if not any(whichna):
+            lst += ", maskna=True"
+        # If everything is NA, can't skip the dtype
+        if skipdtype and all(whichna):
+            skipdtype = False
+
+    if skipdtype:
+        return "%s(%s)" % (cName, lst)
+    else:
+        typename = arr.dtype.name
+        # Quote typename in the output if it is "complex".
+        if typename and not (typename[0].isalpha() and typename.isalnum()):
+            typename = "'%s'" % typename
+
+        lf = ''
+        if 0: # or issubclass(arr.dtype.type, flexible):
+            if arr.dtype.names:
+                typename = "%s" % str(arr.dtype)
+            else:
+                typename = "'%s'" % str(arr.dtype)
+            lf = '\n'+' '*len("array(")
+        return cName + "(%s, %sdtype=%s)" % (lst, lf, typename)
+
+def array_str(a, max_line_width=None, precision=None, suppress_small=None):
+    """
+    Return a string representation of the data in an array.
+
+    The data in the array is returned as a single string.  This function is
+    similar to `array_repr`, the difference being that `array_repr` also
+    returns information on the kind of array and its data type.
+
+    Parameters
+    ----------
+    a : ndarray
+        Input array.
+    max_line_width : int, optional
+        Inserts newlines if text is longer than `max_line_width`.  The
+        default is, indirectly, 75.
+    precision : int, optional
+        Floating point precision.  Default is the current printing precision
+        (usually 8), which can be altered using `set_printoptions`.
+    suppress_small : bool, optional
+        Represent numbers "very close" to zero as zero; default is False.
+        Very close is defined by precision: if the precision is 8, e.g.,
+        numbers smaller (in absolute value) than 5e-9 are represented as
+        zero.
+
+    See Also
+    --------
+    array2string, array_repr, set_printoptions
+
+    Examples
+    --------
+    >>> np.array_str(np.arange(3))
+    '[0 1 2]'
+
+    """
+    return array2string(a, max_line_width, precision, suppress_small, ' ', "", str)
+
+def set_string_function(f, repr=True):
+    """
+    Set a Python function to be used when pretty printing arrays.
+
+    Parameters
+    ----------
+    f : function or None
+        Function to be used to pretty print arrays. The function should expect
+        a single array argument and return a string of the representation of
+        the array. If None, the function is reset to the default NumPy function
+        to print arrays.
+    repr : bool, optional
+        If True (default), the function for pretty printing (``__repr__``)
+        is set, if False the function that returns the default string
+        representation (``__str__``) is set.
+
+    See Also
+    --------
+    set_printoptions, get_printoptions
+
+    Examples
+    --------
+    >>> def pprint(arr):
+    ...     return 'HA! - What are you going to do now?'
+    ...
+    >>> np.set_string_function(pprint)
+    >>> a = np.arange(10)
+    >>> a
+    HA! - What are you going to do now?
+    >>> print a
+    [0 1 2 3 4 5 6 7 8 9]
+
+    We can reset the function to the default:
+
+    >>> np.set_string_function(None)
+    >>> a
+    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+
+    `repr` affects either pretty printing or normal string representation.
+    Note that ``__repr__`` is still affected by setting ``__str__``
+    because the width of each array element in the returned string becomes
+    equal to the length of the result of ``__str__()``.
+
+    >>> x = np.arange(4)
+    >>> np.set_string_function(lambda x:'random', repr=False)
+    >>> x.__str__()
+    'random'
+    >>> x.__repr__()
+    'array([     0,      1,      2,      3])'
+
+    """
+    if f is None:
+        if repr:
+            return multiarray.set_string_function(array_repr, 1)
+        else:
+            return multiarray.set_string_function(array_str, 0)
+    else:
+        return multiarray.set_string_function(f, repr)
+
+set_string_function(array_str, 0)
+set_string_function(array_repr, 1)
+
+little_endian = (sys.byteorder == 'little')
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -440,6 +440,12 @@
     def method_popitem(dct):
         return dct.getanyitem('items')
 
+    def method_pop(dct, s_key, s_dfl=None):
+        dct.dictdef.generalize_key(s_key)
+        if s_dfl is not None:
+            dct.dictdef.generalize_value(s_dfl)
+        return dct.dictdef.read_value()
+
     def _can_only_throw(dic, *ignore):
         if dic1.dictdef.dictkey.custom_eq_hash:
             return None    # r_dict: can throw anything
diff --git a/pypy/jit/codewriter/assembler.py b/pypy/jit/codewriter/assembler.py
--- a/pypy/jit/codewriter/assembler.py
+++ b/pypy/jit/codewriter/assembler.py
@@ -81,10 +81,15 @@
             if not isinstance(value, (llmemory.AddressAsInt,
                                       ComputedIntSymbolic)):
                 value = lltype.cast_primitive(lltype.Signed, value)
-                if allow_short and -128 <= value <= 127:
-                    # emit the constant as a small integer
-                    self.code.append(chr(value & 0xFF))
-                    return True
+                if allow_short:
+                    try:
+                        short_num = -128 <= value <= 127
+                    except TypeError:    # "Symbolics cannot be compared!"
+                        short_num = False
+                    if short_num:
+                        # emit the constant as a small integer
+                        self.code.append(chr(value & 0xFF))
+                        return True
             constants = self.constants_i
         elif kind == 'ref':
             value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -28,6 +28,11 @@
         'fromstring': 'interp_support.fromstring',
         'flatiter': 'interp_numarray.W_FlatIterator',
         'isna': 'interp_numarray.isna',
+        'concatenate': 'interp_numarray.concatenate',
+
+        'set_string_function': 'appbridge.set_string_function',
+        
+        'count_reduce_items': 'interp_numarray.count_reduce_items',
 
         'True_': 'types.Bool.True',
         'False_': 'types.Bool.False',
@@ -67,6 +72,7 @@
         ("copysign", "copysign"),
         ("cos", "cos"),
         ("divide", "divide"),
+        ("true_divide", "true_divide"),
         ("equal", "equal"),
         ("exp", "exp"),
         ("fabs", "fabs"),
@@ -89,6 +95,9 @@
         ("tan", "tan"),
         ('bitwise_and', 'bitwise_and'),
         ('bitwise_or', 'bitwise_or'),
+        ('bitwise_not', 'invert'),
+        ('isnan', 'isnan'),
+        ('isinf', 'isinf'),
     ]:
         interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
 
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -59,7 +59,7 @@
     if not hasattr(a, "max"):
         a = _numpypy.array(a)
     return a.max(axis)
-
+    
 def arange(start, stop=None, step=1, dtype=None):
     '''arange([start], stop[, step], dtype=None)
     Generate values in the half-interval [start, stop).
diff --git a/pypy/module/micronumpy/appbridge.py b/pypy/module/micronumpy/appbridge.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/appbridge.py
@@ -0,0 +1,38 @@
+
+from pypy.rlib.objectmodel import specialize
+
+class AppBridgeCache(object):
+    w__var = None
+    w__std = None
+    w_module = None
+    w_array_repr = None
+    w_array_str = None
+
+    def __init__(self, space):
+        self.w_import = space.appexec([], """():
+        def f():
+            import sys
+            __import__('numpypy.core._methods')
+            return sys.modules['numpypy.core._methods']
+        return f
+        """)
+    
+    @specialize.arg(2)
+    def call_method(self, space, name, *args):
+        w_meth = getattr(self, 'w_' + name)
+        if w_meth is None:
+            if self.w_module is None:
+                self.w_module = space.call_function(self.w_import)
+            w_meth = space.getattr(self.w_module, space.wrap(name))
+            setattr(self, 'w_' + name, w_meth)
+        return space.call_function(w_meth, *args)
+
+def set_string_function(space, w_f, w_repr):
+    cache = get_appbridge_cache(space)
+    if space.is_true(w_repr):
+        cache.w_array_repr = w_f
+    else:
+        cache.w_array_str = w_f
+
+def get_appbridge_cache(space):
+    return space.fromcache(AppBridgeCache)
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -32,13 +32,16 @@
 class BadToken(Exception):
     pass
 
-SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any", "unegative"]
+SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
+                        "unegative", "flat"]
+TWO_ARG_FUNCTIONS = ['take']
 
 class FakeSpace(object):
     w_ValueError = None
     w_TypeError = None
     w_IndexError = None
     w_OverflowError = None
+    w_NotImplementedError = None
     w_None = None
 
     w_bool = "bool"
@@ -53,6 +56,9 @@
         """NOT_RPYTHON"""
         self.fromcache = InternalSpaceCache(self).getorbuild
 
+    def _freeze_(self):
+        return True
+
     def issequence_w(self, w_obj):
         return isinstance(w_obj, ListObject) or isinstance(w_obj, W_NDimArray)
 
@@ -144,6 +150,9 @@
     def allocate_instance(self, klass, w_subtype):
         return instantiate(klass)
 
+    def newtuple(self, list_w):
+        raise ValueError
+
     def len_w(self, w_obj):
         if isinstance(w_obj, ListObject):
             return len(w_obj.items)
@@ -371,12 +380,12 @@
                                                  for arg in self.args]))
 
     def execute(self, interp):
+        arr = self.args[0].execute(interp)
+        if not isinstance(arr, BaseArray):
+            raise ArgumentNotAnArray
         if self.name in SINGLE_ARG_FUNCTIONS:
             if len(self.args) != 1 and self.name != 'sum':
                 raise ArgumentMismatch
-            arr = self.args[0].execute(interp)
-            if not isinstance(arr, BaseArray):
-                raise ArgumentNotAnArray
             if self.name == "sum":
                 if len(self.args)>1:
                     w_res = arr.descr_sum(interp.space,
@@ -396,21 +405,31 @@
             elif self.name == "unegative":
                 neg = interp_ufuncs.get(interp.space).negative
                 w_res = neg.call(interp.space, [arr])
+            elif self.name == "flat":
+                w_res = arr.descr_get_flatiter(interp.space)
             else:
                 assert False # unreachable code
-            if isinstance(w_res, BaseArray):
-                return w_res
-            if isinstance(w_res, FloatObject):
-                dtype = get_dtype_cache(interp.space).w_float64dtype
-            elif isinstance(w_res, BoolObject):
-                dtype = get_dtype_cache(interp.space).w_booldtype
-            elif isinstance(w_res, interp_boxes.W_GenericBox):
-                dtype = w_res.get_dtype(interp.space)
+        elif self.name in TWO_ARG_FUNCTIONS:
+            arg = self.args[1].execute(interp)
+            if not isinstance(arg, BaseArray):
+                raise ArgumentNotAnArray
+            if self.name == 'take':
+                w_res = arr.descr_take(interp.space, arg)
             else:
-                dtype = None
-            return scalar_w(interp.space, dtype, w_res)
+                assert False # unreachable
         else:
             raise WrongFunctionName
+        if isinstance(w_res, BaseArray):
+            return w_res
+        if isinstance(w_res, FloatObject):
+            dtype = get_dtype_cache(interp.space).w_float64dtype
+        elif isinstance(w_res, BoolObject):
+            dtype = get_dtype_cache(interp.space).w_booldtype
+        elif isinstance(w_res, interp_boxes.W_GenericBox):
+            dtype = w_res.get_dtype(interp.space)
+        else:
+            dtype = None
+        return scalar_w(interp.space, dtype, w_res)
 
 _REGEXES = [
     ('-?[\d\.]+', 'number'),
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -8,6 +8,7 @@
 from pypy.tool.sourcetools import func_with_new_name
 
 
+MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else ()
 MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else ()
 
 def new_dtype_getter(name):
@@ -28,6 +29,7 @@
     def convert_to(self, dtype):
         return dtype.box(self.value)
 
+
 class W_GenericBox(Wrappable):
     _attrs_ = ()
 
@@ -93,7 +95,7 @@
     descr_neg = _unaryop_impl("negative")
     descr_abs = _unaryop_impl("absolute")
 
-    def descr_tolist(self, space):
+    def item(self, space):
         return self.get_dtype(space).itemtype.to_builtin_type(space, self)
 
 
@@ -104,7 +106,8 @@
     _attrs_ = ()
 
 class W_IntegerBox(W_NumberBox):
-    pass
+    def int_w(self, space):
+        return space.int_w(self.descr_int(space))
 
 class W_SignedIntegerBox(W_IntegerBox):
     pass
@@ -187,7 +190,7 @@
     __neg__ = interp2app(W_GenericBox.descr_neg),
     __abs__ = interp2app(W_GenericBox.descr_abs),
 
-    tolist = interp2app(W_GenericBox.descr_tolist),
+    tolist = interp2app(W_GenericBox.item),
 )
 
 W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
@@ -231,7 +234,7 @@
     __new__ = interp2app(W_UInt16Box.descr__new__.im_func),
 )
 
-W_Int32Box.typedef = TypeDef("int32", W_SignedIntegerBox.typedef,
+W_Int32Box.typedef = TypeDef("int32", (W_SignedIntegerBox.typedef,) + MIXIN_32,
     __module__ = "numpypy",
     __new__ = interp2app(W_Int32Box.descr__new__.im_func),
 )
@@ -241,24 +244,18 @@
     __new__ = interp2app(W_UInt32Box.descr__new__.im_func),
 )
 
-if LONG_BIT == 32:
-    long_name = "int32"
-elif LONG_BIT == 64:
-    long_name = "int64"
-W_LongBox.typedef = TypeDef(long_name, (W_SignedIntegerBox.typedef, int_typedef,),
-    __module__ = "numpypy",
-   __new__ = interp2app(W_LongBox.descr__new__.im_func),
-)
-
-W_ULongBox.typedef = TypeDef("u" + long_name, W_UnsignedIntegerBox.typedef,
-    __module__ = "numpypy",
-)
-
 W_Int64Box.typedef = TypeDef("int64", (W_SignedIntegerBox.typedef,) + MIXIN_64,
     __module__ = "numpypy",
     __new__ = interp2app(W_Int64Box.descr__new__.im_func),
 )
 
+if LONG_BIT == 32:
+    W_LongBox = W_Int32Box
+    W_ULongBox = W_UInt32Box
+elif LONG_BIT == 64:
+    W_LongBox = W_Int64Box
+    W_ULongBox = W_UInt64Box
+
 W_UInt64Box.typedef = TypeDef("uint64", W_UnsignedIntegerBox.typedef,
     __module__ = "numpypy",
     __new__ = interp2app(W_UInt64Box.descr__new__.im_func),
@@ -283,3 +280,4 @@
 
     __new__ = interp2app(W_Float64Box.descr__new__.im_func),
 )
+
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -89,8 +89,19 @@
     def descr_get_shape(self, space):
         return space.newtuple([])
 
+    def eq(self, space, w_other):
+        w_other = space.call_function(space.gettypefor(W_Dtype), w_other)
+        return space.is_w(self, w_other)
+
+    def descr_eq(self, space, w_other):
+        return space.wrap(self.eq(space, w_other))
+
+    def descr_ne(self, space, w_other):
+        return space.wrap(not self.eq(space, w_other))
+
     def is_int_type(self):
-        return self.kind == SIGNEDLTR or self.kind == UNSIGNEDLTR
+        return (self.kind == SIGNEDLTR or self.kind == UNSIGNEDLTR or
+                self.kind == BOOLLTR)
 
     def is_bool_type(self):
         return self.kind == BOOLLTR
@@ -101,12 +112,15 @@
 
     __str__= interp2app(W_Dtype.descr_str),
     __repr__ = interp2app(W_Dtype.descr_repr),
+    __eq__ = interp2app(W_Dtype.descr_eq),
+    __ne__ = interp2app(W_Dtype.descr_ne),
 
     num = interp_attrproperty("num", cls=W_Dtype),
     kind = interp_attrproperty("kind", cls=W_Dtype),
     type = interp_attrproperty_w("w_box_type", cls=W_Dtype),
     itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
     shape = GetSetProperty(W_Dtype.descr_get_shape),
+    name = interp_attrproperty('name', cls=W_Dtype),
 )
 W_Dtype.typedef.acceptable_as_base_class = False
 
diff --git a/pypy/module/micronumpy/interp_iter.py b/pypy/module/micronumpy/interp_iter.py
--- a/pypy/module/micronumpy/interp_iter.py
+++ b/pypy/module/micronumpy/interp_iter.py
@@ -4,6 +4,49 @@
 from pypy.module.micronumpy.strides import calculate_broadcast_strides,\
      calculate_slice_strides
 
+""" This is a mini-tutorial on iterators, strides, and
+memory layout. It assumes you are familiar with the terms, see
+http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html
+for a more gentle introduction.
+
+Given an array x: x.shape == [5,6],
+
+At which byte in x.data does the item x[3,4] begin?
+if x.strides==[1,5]:
+    pData = x.pData + (x.start + 3*1 + 4*5)*sizeof(x.pData[0])
+    pData = x.pData + (x.start + 24) * sizeof(x.pData[0])
+so the offset of the element is 24 elements after the first
+
+What is the next element in x after coordinates [3,4]?
+if x.order =='C':
+   next == [3,5] => offset is 28
+if x.order =='F':
+   next == [4,4] => offset is 24
+so for the strides [1,5] x is 'F' contiguous
+likewise, for the strides [6,1] x would be 'C' contiguous.
+
+Iterators have an internal representation of the current coordinates
+(indices), the array, strides, and backstrides. A short digression to
+explain backstrides: what is the coordinate and offset after [3,5] in
+the example above?
+if x.order == 'C':
+   next == [4,0] => offset is 4
+if x.order == 'F':
+   next == [4,5] => offset is 25
+Note that in 'C' order we stepped BACKWARDS 24 while 'overflowing' a
+shape dimension
+  which is back 25 and forward 1,
+  which is x.strides[1] * (x.shape[1] - 1) + x.strides[0]
+so if we precalculate the overflow backstride as 
+[x.strides[i] * (x.shape[i] - 1) for i in range(len(x.shape))]
+we can go faster.
+All the calculations happen in next()
+
+next_step_x() tries to do the iteration for a number of steps at once,
+but then we cannot gaurentee that we only overflow one single shape 
+dimension, perhaps we could overflow times in one big step.
+"""
+
 # structures to describe slicing
 
 class Chunk(object):
@@ -17,6 +60,10 @@
         if self.step != 0:
             shape.append(self.lgt)
 
+    def __repr__(self):
+        return 'Chunk(%d, %d, %d, %d)' % (self.start, self.stop, self.step,
+                                          self.lgt)
+
 class BaseTransform(object):
     pass
 
@@ -51,9 +98,9 @@
         self.size = size
 
     def next(self, shapelen):
-        return self._next(1)
+        return self.next_skip_x(1)
 
-    def _next(self, ofs):
+    def next_skip_x(self, ofs):
         arr = instantiate(ArrayIterator)
         arr.size = self.size
         arr.offset = self.offset + ofs
@@ -61,7 +108,7 @@
 
     def next_no_increase(self, shapelen):
         # a hack to make JIT believe this is always virtual
-        return self._next(0)
+        return self.next_skip_x(0)
 
     def done(self):
         return self.offset >= self.size
@@ -133,6 +180,36 @@
         res._done = done
         return res
 
+    @jit.unroll_safe
+    def next_skip_x(self, shapelen, step):
+        shapelen = jit.promote(len(self.res_shape))
+        offset = self.offset
+        indices = [0] * shapelen
+        for i in range(shapelen):
+            indices[i] = self.indices[i]
+        done = False
+        for i in range(shapelen - 1, -1, -1):
+            if indices[i] < self.res_shape[i] - step:
+                indices[i] += step
+                offset += self.strides[i] * step
+                break
+            else:
+                remaining_step = (indices[i] + step) // self.res_shape[i]
+                this_i_step = step - remaining_step * self.res_shape[i]
+                offset += self.strides[i] * this_i_step
+                indices[i] = indices[i] +  this_i_step
+                step = remaining_step
+        else:
+            done = True
+        res = instantiate(ViewIterator)
+        res.offset = offset
+        res.indices = indices
+        res.strides = self.strides
+        res.backstrides = self.backstrides
+        res.res_shape = self.res_shape
+        res._done = done
+        return res
+
     def apply_transformations(self, arr, transformations):
         v = BaseIterator.apply_transformations(self, arr, transformations)
         if len(arr.shape) == 1:
@@ -153,8 +230,13 @@
 class AxisIterator(BaseIterator):
     def __init__(self, start, dim, shape, strides, backstrides):
         self.res_shape = shape[:]
-        self.strides = strides[:dim] + [0] + strides[dim:]
-        self.backstrides = backstrides[:dim] + [0] + backstrides[dim:]
+        if len(shape) == len(strides):
+            # keepdims = True
+            self.strides = strides[:dim] + [0] + strides[dim + 1:]
+            self.backstrides = backstrides[:dim] + [0] + backstrides[dim + 1:]
+        else:
+            self.strides = strides[:dim] + [0] + strides[dim:]
+            self.backstrides = backstrides[:dim] + [0] + backstrides[dim:]
         self.first_line = True
         self.indices = [0] * len(shape)
         self._done = False
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -1,16 +1,20 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped
+from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.module.micronumpy import interp_ufuncs, interp_dtype, signature,\
-     interp_boxes
-from pypy.module.micronumpy.strides import calculate_slice_strides
+from pypy.module.micronumpy import (interp_ufuncs, interp_dtype, interp_boxes,
+    signature, support)
+from pypy.module.micronumpy.strides import (calculate_slice_strides,
+    shape_agreement, find_shape_and_elems, get_shape_from_iterable,
+    calc_new_strides, to_coords)
 from pypy.rlib import jit
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.rstring import StringBuilder
-from pypy.module.micronumpy.interp_iter import ArrayIterator, OneDimIterator,\
-     SkipLastAxisIterator, Chunk, ViewIterator
+from pypy.module.micronumpy.interp_iter import (ArrayIterator, OneDimIterator,
+    SkipLastAxisIterator, Chunk, ViewIterator)
+from pypy.module.micronumpy.appbridge import get_appbridge_cache
+
 
 numpy_driver = jit.JitDriver(
     greens=['shapelen', 'sig'],
@@ -58,176 +62,21 @@
     reds=['idx', 'idxi', 'frame', 'arr'],
     name='numpy_filterset',
 )
-
-def _find_shape_and_elems(space, w_iterable):
-    shape = [space.len_w(w_iterable)]
-    batch = space.listview(w_iterable)
-    while True:
-        new_batch = []
-        if not batch:
-            return shape, []
-        if not space.issequence_w(batch[0]):
-            for elem in batch:
-                if space.issequence_w(elem):
-                    raise OperationError(space.w_ValueError, space.wrap(
-                        "setting an array element with a sequence"))
-            return shape, batch
-        size = space.len_w(batch[0])
-        for w_elem in batch:
-            if not space.issequence_w(w_elem) or space.len_w(w_elem) != size:
-                raise OperationError(space.w_ValueError, space.wrap(
-                    "setting an array element with a sequence"))
-            new_batch += space.listview(w_elem)
-        shape.append(size)
-        batch = new_batch
-
-def shape_agreement(space, shape1, shape2):
-    ret = _shape_agreement(shape1, shape2)
-    if len(ret) < max(len(shape1), len(shape2)):
-        raise OperationError(space.w_ValueError,
-            space.wrap("operands could not be broadcast together with shapes (%s) (%s)" % (
-                ",".join([str(x) for x in shape1]),
-                ",".join([str(x) for x in shape2]),
-            ))
-        )
-    return ret
-
-def _shape_agreement(shape1, shape2):
-    """ Checks agreement about two shapes with respect to broadcasting. Returns
-    the resulting shape.
-    """
-    lshift = 0
-    rshift = 0
-    if len(shape1) > len(shape2):
-        m = len(shape1)
-        n = len(shape2)
-        rshift = len(shape2) - len(shape1)
-        remainder = shape1
-    else:
-        m = len(shape2)
-        n = len(shape1)
-        lshift = len(shape1) - len(shape2)
-        remainder = shape2
-    endshape = [0] * m
-    indices1 = [True] * m
-    indices2 = [True] * m
-    for i in range(m - 1, m - n - 1, -1):
-        left = shape1[i + lshift]
-        right = shape2[i + rshift]
-        if left == right:
-            endshape[i] = left
-        elif left == 1:
-            endshape[i] = right
-            indices1[i + lshift] = False
-        elif right == 1:
-            endshape[i] = left
-            indices2[i + rshift] = False
-        else:
-            return []
-            #raise OperationError(space.w_ValueError, space.wrap(
-            #    "frames are not aligned"))
-    for i in range(m - n):
-        endshape[i] = remainder[i]
-    return endshape
-
-def get_shape_from_iterable(space, old_size, w_iterable):
-    new_size = 0
-    new_shape = []
-    if space.isinstance_w(w_iterable, space.w_int):
-        new_size = space.int_w(w_iterable)
-        if new_size < 0:
-            new_size = old_size
-        new_shape = [new_size]
-    else:
-        neg_dim = -1
-        batch = space.listview(w_iterable)
-        new_size = 1
-        if len(batch) < 1:
-            if old_size == 1:
-                # Scalars can have an empty size.
-                new_size = 1
-            else:
-                new_size = 0
-        new_shape = []
-        i = 0
-        for elem in batch:
-            s = space.int_w(elem)
-            if s < 0:
-                if neg_dim >= 0:
-                    raise OperationError(space.w_ValueError, space.wrap(
-                             "can only specify one unknown dimension"))
-                s = 1
-                neg_dim = i
-            new_size *= s
-            new_shape.append(s)
-            i += 1
-        if neg_dim >= 0:
-            new_shape[neg_dim] = old_size / new_size
-            new_size *= new_shape[neg_dim]
-    if new_size != old_size:
-        raise OperationError(space.w_ValueError,
-                space.wrap("total size of new array must be unchanged"))
-    return new_shape
-
-# Recalculating strides. Find the steps that the iteration does for each
-# dimension, given the stride and shape. Then try to create a new stride that
-# fits the new shape, using those steps. If there is a shape/step mismatch
-# (meaning that the realignment of elements crosses from one step into another)
-# return None so that the caller can raise an exception.
-def calc_new_strides(new_shape, old_shape, old_strides, order):
-    # Return the proper strides for new_shape, or None if the mapping crosses
-    # stepping boundaries
-
-    # Assumes that prod(old_shape) == prod(new_shape), len(old_shape) > 1, and
-    # len(new_shape) > 0
-    steps = []
-    last_step = 1
-    oldI = 0
-    new_strides = []
-    if order == 'F':
-        for i in range(len(old_shape)):
-            steps.append(old_strides[i] / last_step)
-            last_step *= old_shape[i]
-        cur_step = steps[0]
-        n_new_elems_used = 1
-        n_old_elems_to_use = old_shape[0]
-        for s in new_shape:
-            new_strides.append(cur_step * n_new_elems_used)
-            n_new_elems_used *= s
-            while n_new_elems_used > n_old_elems_to_use:
-                oldI += 1
-                if steps[oldI] != steps[oldI - 1]:
-                    return None
-                n_old_elems_to_use *= old_shape[oldI]
-            if n_new_elems_used == n_old_elems_to_use:
-                oldI += 1
-                if oldI < len(old_shape):
-                    cur_step = steps[oldI]
-                    n_old_elems_to_use *= old_shape[oldI]
-    elif order == 'C':
-        for i in range(len(old_shape) - 1, -1, -1):
-            steps.insert(0, old_strides[i] / last_step)
-            last_step *= old_shape[i]
-        cur_step = steps[-1]
-        n_new_elems_used = 1
-        oldI = -1
-        n_old_elems_to_use = old_shape[-1]
-        for i in range(len(new_shape) - 1, -1, -1):
-            s = new_shape[i]
-            new_strides.insert(0, cur_step * n_new_elems_used)
-            n_new_elems_used *= s
-            while n_new_elems_used > n_old_elems_to_use:
-                oldI -= 1
-                if steps[oldI] != steps[oldI + 1]:
-                    return None
-                n_old_elems_to_use *= old_shape[oldI]
-            if n_new_elems_used == n_old_elems_to_use:
-                oldI -= 1
-                if oldI >= -len(old_shape):
-                    cur_step = steps[oldI]
-                    n_old_elems_to_use *= old_shape[oldI]
-    assert len(new_strides) == len(new_shape)
-    return new_strides
+take_driver = jit.JitDriver(
+    greens=['shapelen', 'sig'],
+    reds=['index_i', 'res_i', 'concr', 'index', 'res'],
+    name='numpy_take',
+)
+flat_get_driver = jit.JitDriver(
+    greens=['shapelen', 'base'],
+    reds=['step', 'ri', 'basei', 'res'],
+    name='numpy_flatget',
+)
+flat_set_driver = jit.JitDriver(
+    greens=['shapelen', 'base'],
+    reds=['step', 'ai', 'lngth', 'arr', 'basei'],
+    name='numpy_flatset',
+)
 
 class BaseArray(Wrappable):
     _attrs_ = ["invalidates", "shape", 'size']
@@ -268,6 +117,7 @@
     descr_pos = _unaryop_impl("positive")
     descr_neg = _unaryop_impl("negative")
     descr_abs = _unaryop_impl("absolute")
+    descr_invert = _unaryop_impl("invert")
 
     def _binop_impl(ufunc_name):
         def impl(self, space, w_other):
@@ -310,9 +160,11 @@
     def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False):
         def impl(self, space, w_axis=None):
             if space.is_w(w_axis, space.w_None):
-                w_axis = space.wrap(-1)
+                axis = -1
+            else:
+                axis = space.int_w(w_axis)
             return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space,
-                                        self, True, promote_to_largest, w_axis)
+                                        self, True, promote_to_largest, axis)
         return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name)
 
     descr_sum = _reduce_ufunc_impl("add")
@@ -430,21 +282,22 @@
     def descr_copy(self, space):
         return self.copy(space)
 
-    def descr_flatten(self, space):
-        return self.flatten(space)
+    def descr_flatten(self, space, w_order=None):
+        if isinstance(self, Scalar):
+            # scalars have no storage
+            return self.descr_reshape(space, [space.wrap(1)])
+        concr = self.get_concrete()
+        w_res = concr.descr_ravel(space, w_order)
+        if w_res.storage == concr.storage:
+            return w_res.copy(space)
+        return w_res
 
     def copy(self, space):
         return self.get_concrete().copy(space)
 
     def empty_copy(self, space, dtype):
         shape = self.shape
-        size = 1
-        for elem in shape:
-            size *= elem
-        return W_NDimArray(size, shape[:], dtype, 'C')
-
-    def flatten(self, space):
-        return self.get_concrete().flatten(space)
+        return W_NDimArray(support.product(shape), shape[:], dtype, 'C')
 
     def descr_len(self, space):
         if len(self.shape):
@@ -453,33 +306,32 @@
             "len() of unsized object"))
 
     def descr_repr(self, space):
-        res = StringBuilder()
-        res.append("array(")
-        concrete = self.get_concrete_or_scalar()
-        dtype = concrete.find_dtype()
-        if not concrete.size:
-            res.append('[]')
-            if len(self.shape) > 1:
-                # An empty slice reports its shape
-                res.append(", shape=(")
-                self_shape = str(self.shape)
-                res.append_slice(str(self_shape), 1, len(self_shape) - 1)
-                res.append(')')
-        else:
-            concrete.to_str(space, 1, res, indent='       ')
-        if (dtype is not interp_dtype.get_dtype_cache(space).w_float64dtype and
-            not (dtype.kind == interp_dtype.SIGNEDLTR and
-            dtype.itemtype.get_element_size() == rffi.sizeof(lltype.Signed)) or
-            not self.size):
-            res.append(", dtype=" + dtype.name)
-        res.append(")")
-        return space.wrap(res.build())
+        cache = get_appbridge_cache(space)
+        if cache.w_array_repr is None:
+            return space.wrap(self.dump_data())
+        return space.call_function(cache.w_array_repr, self)
+
+    def dump_data(self):
+        concr = self.get_concrete()
+        i = concr.create_iter()
+        first = True
+        s = StringBuilder()
+        s.append('array([')
+        while not i.done():
+            if first:
+                first = False
+            else:
+                s.append(', ')
+            s.append(concr.dtype.itemtype.str_format(concr.getitem(i.offset)))
+            i = i.next(len(concr.shape))
+        s.append('])')
+        return s.build()
 
     def descr_str(self, space):
-        ret = StringBuilder()
-        concrete = self.get_concrete_or_scalar()
-        concrete.to_str(space, 0, ret, ' ')
-        return space.wrap(ret.build())
+        cache = get_appbridge_cache(space)
+        if cache.w_array_str is None:
+            return space.wrap(self.dump_data())
+        return space.call_function(cache.w_array_str, self)
 
     @jit.unroll_safe
     def _single_item_result(self, space, w_idx):
@@ -519,7 +371,7 @@
 
     def count_all_true(self, arr):
         sig = arr.find_sig()
-        frame = sig.create_frame(self)
+        frame = sig.create_frame(arr)
         shapelen = len(arr.shape)
         s = 0
         iter = None
@@ -533,6 +385,9 @@
 
     def getitem_filter(self, space, arr):
         concr = arr.get_concrete()
+        if concr.size > self.size:
+            raise OperationError(space.w_IndexError,
+                                 space.wrap("index out of range for array"))
         size = self.count_all_true(concr)
         res = W_NDimArray(size, [size], self.find_dtype())
         ri = ArrayIterator(size)
@@ -541,7 +396,7 @@
         sig = self.find_sig()
         frame = sig.create_frame(self)
         v = None
-        while not frame.done():
+        while not ri.done():
             filter_driver.jit_merge_point(concr=concr, argi=argi, ri=ri,
                                           frame=frame, v=v, res=res, sig=sig,
                                           shapelen=shapelen, self=self)
@@ -581,7 +436,7 @@
             item = concrete._index_of_single_item(space, w_idx)
             return concrete.getitem(item)
         chunks = self._prepare_slice_args(space, w_idx)
-        return space.wrap(self.create_slice(chunks))
+        return self.create_slice(chunks)
 
     def descr_setitem(self, space, w_idx, w_value):
         self.invalidated()
@@ -635,8 +490,11 @@
             w_shape = args_w[0]
         else:
             w_shape = space.newtuple(args_w)
+        new_shape = get_shape_from_iterable(space, self.size, w_shape)
+        return self.reshape(space, new_shape)
+        
+    def reshape(self, space, new_shape):
         concrete = self.get_concrete()
-        new_shape = get_shape_from_iterable(space, concrete.size, w_shape)
         # Since we got to here, prod(new_shape) == self.size
         new_strides = calc_new_strides(new_shape, concrete.shape,
                                      concrete.strides, concrete.order)
@@ -647,7 +505,7 @@
             for nd in range(ndims):
                 new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
             arr = W_NDimSlice(concrete.start, new_strides, new_backstrides,
-                              new_shape, self)
+                              new_shape, concrete)
         else:
             # Create copy with contiguous data
             arr = concrete.copy(space)
@@ -657,7 +515,7 @@
     def descr_tolist(self, space):
         if len(self.shape) == 0:
             assert isinstance(self, Scalar)
-            return self.value.descr_tolist(space)
+            return self.value.item(space)
         w_result = space.newlist([])
         for i in range(self.shape[0]):
             space.call_method(w_result, "append",
@@ -674,17 +532,13 @@
             w_denom = space.wrap(self.shape[dim])
         return space.div(self.descr_sum_promote(space, w_axis), w_denom)
 
-    def descr_var(self, space):
-        # var = mean((values - mean(values)) ** 2)
-        w_res = self.descr_sub(space, self.descr_mean(space, space.w_None))
-        assert isinstance(w_res, BaseArray)
-        w_res = w_res.descr_pow(space, space.wrap(2))
-        assert isinstance(w_res, BaseArray)
-        return w_res.descr_mean(space, space.w_None)
+    def descr_var(self, space, w_axis=None):
+        return get_appbridge_cache(space).call_method(space, '_var', self,
+                                                      w_axis)
 
-    def descr_std(self, space):
-        # std(v) = sqrt(var(v))
-        return interp_ufuncs.get(space).sqrt.call(space, [self.descr_var(space)])
+    def descr_std(self, space, w_axis=None):
+        return get_appbridge_cache(space).call_method(space, '_std', self,
+                                                      w_axis)
 
     def descr_fill(self, space, w_value):
         concr = self.get_concrete_or_scalar()
@@ -717,6 +571,16 @@
         return space.wrap(W_NDimSlice(concrete.start, strides,
                                       backstrides, shape, concrete))
 
+    def descr_ravel(self, space, w_order=None):
+        if w_order is None or space.is_w(w_order, space.w_None):
+            order = 'C'
+        else:
+            order = space.str_w(w_order)
+        if order != 'C':
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                "order not implemented"))
+        return self.descr_reshape(space, [space.wrap(-1)])
+
     def descr_get_flatiter(self, space):
         return space.wrap(W_FlatIterator(self))
 
@@ -746,6 +610,60 @@
     def supports_fast_slicing(self):
         return False
 
+    def descr_compress(self, space, w_obj, w_axis=None):
+        index = convert_to_array(space, w_obj)
+        return self.getitem_filter(space, index)
+
+    def descr_take(self, space, w_obj, w_axis=None):
+        index = convert_to_array(space, w_obj).get_concrete()
+        concr = self.get_concrete()
+        if space.is_w(w_axis, space.w_None):
+            concr = concr.descr_ravel(space)
+        else:
+            raise OperationError(space.w_NotImplementedError,
+                                 space.wrap("axis unsupported for take"))
+        index_i = index.create_iter()
+        res_shape = index.shape
+        size = support.product(res_shape)
+        res = W_NDimArray(size, res_shape[:], concr.dtype, concr.order)
+        res_i = res.create_iter()
+        shapelen = len(index.shape)
+        sig = concr.find_sig()
+        while not index_i.done():
+            take_driver.jit_merge_point(index_i=index_i, index=index,
+                                        res_i=res_i, concr=concr,
+                                        res=res,
+                                        shapelen=shapelen, sig=sig)
+            w_item = index._getitem_long(space, index_i.offset)
+            res.setitem(res_i.offset, concr.descr_getitem(space, w_item))
+            index_i = index_i.next(shapelen)
+            res_i = res_i.next(shapelen)
+        return res
+
+    def _getitem_long(self, space, offset):
+        # an obscure hack to not have longdtype inside a jitted loop
+        longdtype = interp_dtype.get_dtype_cache(space).w_longdtype
+        return self.getitem(offset).convert_to(longdtype).item(
+            space)
+
+    def descr_item(self, space, w_arg=None):
+        if space.is_w(w_arg, space.w_None):
+            if not isinstance(self, Scalar):
+                raise OperationError(space.w_ValueError, space.wrap("index out of bounds"))
+            return self.value.item(space)
+        if space.isinstance_w(w_arg, space.w_int):
+            if isinstance(self, Scalar):
+                raise OperationError(space.w_ValueError, space.wrap("index out of bounds"))
+            concr = self.get_concrete()
+            i = to_coords(space, self.shape, concr.size, concr.order, w_arg)[0]
+            # XXX a bit around
+            item = self.descr_getitem(space, space.newtuple([space.wrap(x)
+                                             for x in i]))
+            assert isinstance(item, interp_boxes.W_GenericBox)
+            return item.item(space)
+        raise OperationError(space.w_NotImplementedError, space.wrap(
+            "non-int arg not supported"))
+
 def convert_to_array(space, w_obj):
     if isinstance(w_obj, BaseArray):
         return w_obj
@@ -771,22 +689,15 @@
         self.shape = []
         BaseArray.__init__(self, [])
         self.dtype = dtype
+        assert isinstance(value, interp_boxes.W_GenericBox)
         self.value = value
 
     def find_dtype(self):
         return self.dtype
 
-    def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
-        builder.append(self.dtype.itemtype.str_format(self.value))
-
     def copy(self, space):
         return Scalar(self.dtype, self.value)
 
-    def flatten(self, space):
-        array = W_NDimArray(self.size, [self.size], self.dtype)
-        array.setitem(0, self.value)
-        return array
-
     def fill(self, space, w_value):
         self.value = self.dtype.coerce(space, w_value)
 
@@ -796,6 +707,11 @@
     def get_concrete_or_scalar(self):
         return self
 
+    def reshape(self, space, new_shape):
+        size = support.product(new_shape)
+        res = W_NDimArray(size, new_shape, self.dtype, 'C')
+        res.setitem(0, self.value)
+        return res
 
 class VirtualArray(BaseArray):
     """
@@ -852,12 +768,9 @@
 
 class VirtualSlice(VirtualArray):
     def __init__(self, child, chunks, shape):
-        size = 1
-        for sh in shape:
-            size *= sh
         self.child = child
         self.chunks = chunks
-        self.size = size
+        self.size = support.product(shape)
         VirtualArray.__init__(self, 'slice', shape, child.find_dtype())
 
     def create_sig(self):
@@ -876,11 +789,12 @@
 
 
 class Call1(VirtualArray):
-    def __init__(self, ufunc, name, shape, res_dtype, values):
+    def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, values):
         VirtualArray.__init__(self, name, shape, res_dtype)
         self.values = values
         self.size = values.size
         self.ufunc = ufunc
+        self.calc_dtype = calc_dtype
 
     def _del_sources(self):
         self.values = None
@@ -902,9 +816,7 @@
         self.left = left
         self.right = right
         self.calc_dtype = calc_dtype
-        self.size = 1
-        for s in self.shape:
-            self.size *= s
+        self.size = support.product(self.shape)
 
     def _del_sources(self):
         self.left = None
@@ -1014,89 +926,6 @@
         self.strides = strides
         self.backstrides = backstrides
 
-    def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
-        '''Modifies builder with a representation of the array/slice
-        The items will be seperated by a comma if comma is 1
-        Multidimensional arrays/slices will span a number of lines,
-        each line will begin with indent.
-        '''
-        size = self.size
-        ccomma = ',' * comma
-        ncomma = ',' * (1 - comma)
-        dtype = self.find_dtype()
-        if size < 1:
-            builder.append('[]')
-            return
-        if size > 1000:
-            # Once this goes True it does not go back to False for recursive
-            # calls
-            use_ellipsis = True
-        ndims = len(self.shape)
-        if ndims == 0:
-            builder.append(dtype.itemtype.str_format(self.getitem(0)))
-            return
-        i = 0
-        builder.append('[')
-        if ndims > 1:
-            if use_ellipsis:
-                for i in range(min(3, self.shape[0])):
-                    if i > 0:
-                        builder.append(ccomma + '\n')
-                        if ndims >= 3:
-                            builder.append('\n' + indent)
-                        else:
-                            builder.append(indent)
-                    view = self.create_slice([Chunk(i, 0, 0, 1)]).get_concrete()
-                    view.to_str(space, comma, builder, indent=indent + ' ',
-                                                    use_ellipsis=use_ellipsis)
-                if i < self.shape[0] - 1:
-                    builder.append(ccomma + '\n' + indent + '...' + ncomma)
-                    i = self.shape[0] - 3
-                else:
-                    i += 1
-            while i < self.shape[0]:
-                if i > 0:
-                    builder.append(ccomma + '\n')
-                    if ndims >= 3:
-                        builder.append('\n' + indent)
-                    else:
-                        builder.append(indent)
-                # create_slice requires len(chunks) > 1 in order to reduce
-                # shape
-                view = self.create_slice([Chunk(i, 0, 0, 1)]).get_concrete()
-                view.to_str(space, comma, builder, indent=indent + ' ',
-                                                    use_ellipsis=use_ellipsis)
-                i += 1
-        elif ndims == 1:
-            spacer = ccomma + ' '
-            item = self.start
-            # An iterator would be a nicer way to walk along the 1d array, but
-            # how do I reset it if printing ellipsis? iterators have no
-            # "set_offset()"
-            i = 0
-            if use_ellipsis:
-                for i in range(min(3, self.shape[0])):
-                    if i > 0:
-                        builder.append(spacer)
-                    builder.append(dtype.itemtype.str_format(self.getitem(item)))
-                    item += self.strides[0]
-                if i < self.shape[0] - 1:
-                    # Add a comma only if comma is False - this prevents adding
-                    # two commas
-                    builder.append(spacer + '...' + ncomma)
-                    # Ugly, but can this be done with an iterator?
-                    item = self.start + self.backstrides[0] - 2 * self.strides[0]
-                    i = self.shape[0] - 3
-                else:
-                    i += 1
-            while i < self.shape[0]:
-                if i > 0:
-                    builder.append(spacer)
-                builder.append(dtype.itemtype.str_format(self.getitem(item)))
-                item += self.strides[0]
-                i += 1
-        builder.append(']')
-
     @jit.unroll_safe
     def _index_of_single_item(self, space, w_idx):
         if space.isinstance_w(w_idx, space.w_int):
@@ -1169,15 +998,6 @@
         array.setslice(space, self)
         return array
 
-    def flatten(self, space):
-        array = W_NDimArray(self.size, [self.size], self.dtype, self.order)
-        if self.supports_fast_slicing():
-            array._fast_setslice(space, self)
-        else:
-            arr = SliceArray(array.shape, array.dtype, array, self, no_broadcast=True)
-            array._sliceloop(arr)
-        return array
-
     def fill(self, space, w_value):
         self.setslice(space, scalar_w(space, self.dtype, w_value))
 
@@ -1192,13 +1012,10 @@
         assert isinstance(parent, ConcreteArray)
         if isinstance(parent, W_NDimSlice):
             parent = parent.parent
-        size = 1
-        for sh in shape:
-            size *= sh
         self.strides = strides
         self.backstrides = backstrides
-        ViewArray.__init__(self, size, shape, parent.dtype, parent.order,
-                               parent)
+        ViewArray.__init__(self, support.product(shape), shape, parent.dtype,
+                           parent.order, parent)
         self.start = start
 
     def create_iter(self):
@@ -1274,27 +1091,42 @@
             shape.append(item)
     return size, shape
 
-def array(space, w_item_or_iterable, w_dtype=None, w_order=NoneNotWrapped):
+ at unwrap_spec(subok=bool, copy=bool, ownmaskna=bool)
+def array(space, w_item_or_iterable, w_dtype=None, w_order=None,
+          subok=True, copy=True, w_maskna=None, ownmaskna=False):
     # find scalar
+    if w_maskna is None:
+        w_maskna = space.w_None
+    if (not subok or not space.is_w(w_maskna, space.w_None) or
+        ownmaskna):
+        raise OperationError(space.w_NotImplementedError, space.wrap("Unsupported args"))
     if not space.issequence_w(w_item_or_iterable):
-        if space.is_w(w_dtype, space.w_None):
+        if w_dtype is None or space.is_w(w_dtype, space.w_None):
             w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
                                                           w_item_or_iterable)
         dtype = space.interp_w(interp_dtype.W_Dtype,
             space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
         )
         return scalar_w(space, dtype, w_item_or_iterable)
-    if w_order is None:
+    if space.is_w(w_order, space.w_None) or w_order is None:
         order = 'C'
     else:
         order = space.str_w(w_order)
         if order != 'C':  # or order != 'F':
             raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
                                   order)
-    shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
+    if isinstance(w_item_or_iterable, BaseArray):
+        if (not space.is_w(w_dtype, space.w_None) and
+            w_item_or_iterable.find_dtype() is not w_dtype):
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                "copying over different dtypes unsupported"))
+        if copy:
+            return w_item_or_iterable.copy(space)
+        return w_item_or_iterable
+    shape, elems_w = find_shape_and_elems(space, w_item_or_iterable)
     # they come back in C order
     size = len(elems_w)
-    if space.is_w(w_dtype, space.w_None):
+    if w_dtype is None or space.is_w(w_dtype, space.w_None):
         w_dtype = None
         for w_elem in elems_w:
             w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
@@ -1322,6 +1154,8 @@
         space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
     )
     size, shape = _find_size_and_shape(space, w_size)
+    if not shape:
+        return scalar_w(space, dtype, space.wrap(0))
     return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
 
 def ones(space, w_size, w_dtype=None):
@@ -1330,17 +1164,66 @@
     )
 
     size, shape = _find_size_and_shape(space, w_size)
+    if not shape:
+        return scalar_w(space, dtype, space.wrap(1))
     arr = W_NDimArray(size, shape[:], dtype=dtype)
     one = dtype.box(1)
     arr.dtype.fill(arr.storage, one, 0, size)
     return space.wrap(arr)
 
+ at unwrap_spec(arr=BaseArray, skipna=bool, keepdims=bool)
+def count_reduce_items(space, arr, w_axis=None, skipna=False, keepdims=True):
+    if not keepdims:
+        raise OperationError(space.w_NotImplementedError, space.wrap("unsupported"))
+    if space.is_w(w_axis, space.w_None):
+        return space.wrap(support.product(arr.shape))
+    if space.isinstance_w(w_axis, space.w_int):
+        return space.wrap(arr.shape[space.int_w(w_axis)])
+    s = 1
+    elems = space.fixedview(w_axis)
+    for w_elem in elems:
+        s *= arr.shape[space.int_w(w_elem)]
+    return space.wrap(s)
+
 def dot(space, w_obj, w_obj2):
     w_arr = convert_to_array(space, w_obj)
     if isinstance(w_arr, Scalar):
         return convert_to_array(space, w_obj2).descr_dot(space, w_arr)
     return w_arr.descr_dot(space, w_obj2)
 
+ at unwrap_spec(axis=int)
+def concatenate(space, w_args, axis=0):
+    args_w = space.listview(w_args)
+    if len(args_w) == 0:
+        raise OperationError(space.w_ValueError, space.wrap("concatenation of zero-length sequences is impossible"))
+    args_w = [convert_to_array(space, w_arg) for w_arg in args_w]
+    dtype = args_w[0].find_dtype()
+    shape = args_w[0].shape[:]
+    if len(shape) <= axis:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("bad axis argument"))
+    for arr in args_w[1:]:
+        dtype = interp_ufuncs.find_binop_result_dtype(space, dtype,
+                                                      arr.find_dtype())
+        if len(arr.shape) <= axis:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("bad axis argument"))
+        for i, axis_size in enumerate(arr.shape):
+            if len(arr.shape) != len(shape) or (i != axis and axis_size != shape[i]):
+                raise OperationError(space.w_ValueError, space.wrap(
+                    "array dimensions must agree except for axis being concatenated"))
+            elif i == axis:
+                shape[i] += axis_size
+    res = W_NDimArray(support.product(shape), shape, dtype, 'C')
+    chunks = [Chunk(0, i, 1, i) for i in shape]
+    axis_start = 0
+    for arr in args_w:
+        chunks[axis] = Chunk(axis_start, axis_start + arr.shape[axis], 1,
+                             arr.shape[axis])
+        res.create_slice(chunks).setslice(space, arr)
+        axis_start += arr.shape[axis]
+    return res
+
 BaseArray.typedef = TypeDef(
     'ndarray',
     __module__ = "numpypy",
@@ -1378,6 +1261,7 @@
 
     __and__ = interp2app(BaseArray.descr_and),
     __or__ = interp2app(BaseArray.descr_or),
+    __invert__ = interp2app(BaseArray.descr_invert),
 
     __repr__ = interp2app(BaseArray.descr_repr),
     __str__ = interp2app(BaseArray.descr_str),
@@ -1388,9 +1272,11 @@
                            BaseArray.descr_set_shape),
     size = GetSetProperty(BaseArray.descr_get_size),
     ndim = GetSetProperty(BaseArray.descr_get_ndim),
+    item = interp2app(BaseArray.descr_item),
 
     T = GetSetProperty(BaseArray.descr_get_transpose),
     flat = GetSetProperty(BaseArray.descr_get_flatiter),
+    ravel = interp2app(BaseArray.descr_ravel),
 
     mean = interp2app(BaseArray.descr_mean),
     sum = interp2app(BaseArray.descr_sum),
@@ -1411,6 +1297,8 @@
     flatten = interp2app(BaseArray.descr_flatten),
     reshape = interp2app(BaseArray.descr_reshape),
     tolist = interp2app(BaseArray.descr_tolist),
+    take = interp2app(BaseArray.descr_take),
+    compress = interp2app(BaseArray.descr_compress),
 )
 
 
@@ -1419,31 +1307,122 @@
     @jit.unroll_safe
     def __init__(self, arr):
         arr = arr.get_concrete()
-        size = 1
-        for sh in arr.shape:
-            size *= sh
         self.strides = [arr.strides[-1]]
         self.backstrides = [arr.backstrides[-1]]
-        ViewArray.__init__(self, size, [size], arr.dtype, arr.order,
-                               arr)
         self.shapelen = len(arr.shape)
-        self.iter = OneDimIterator(arr.start, self.strides[0],
-                                   self.shape[0])
+        sig = arr.find_sig()
+        self.iter = sig.create_frame(arr).get_final_iter()
+        self.base = arr
+        self.index = 0
+        ViewArray.__init__(self, arr.size, [arr.size], arr.dtype, arr.order,
+                           arr)
 
     def descr_next(self, space):
         if self.iter.done():
             raise OperationError(space.w_StopIteration, space.w_None)
-        result = self.getitem(self.iter.offset)
+        result = self.base.getitem(self.iter.offset)
         self.iter = self.iter.next(self.shapelen)
+        self.index += 1
         return result
 
     def descr_iter(self):
         return self
 
+    def descr_index(self, space):
+        return space.wrap(self.index)
+
+    def descr_coords(self, space):
+        coords, step, lngth = to_coords(space, self.base.shape, 
+                            self.base.size, self.base.order, 
+                            space.wrap(self.index))
+        return space.newtuple([space.wrap(c) for c in coords])
+
+    @jit.unroll_safe
+    def descr_getitem(self, space, w_idx):
+        if not (space.isinstance_w(w_idx, space.w_int) or
+            space.isinstance_w(w_idx, space.w_slice)):
+            raise OperationError(space.w_IndexError,
+                                 space.wrap('unsupported iterator index'))
+        base = self.base
+        start, stop, step, lngth = space.decode_index4(w_idx, base.size)
+        # setslice would have been better, but flat[u:v] for arbitrary
+        # shapes of array a cannot be represented as a[x1:x2, y1:y2]
+        basei = ViewIterator(base.start, base.strides,
+                               base.backstrides,base.shape)
+        shapelen = len(base.shape)
+        basei = basei.next_skip_x(shapelen, start)
+        if lngth <2:
+            return base.getitem(basei.offset)
+        ri = ArrayIterator(lngth)
+        res = W_NDimArray(lngth, [lngth], base.dtype,
+                                    base.order)
+        while not ri.done():
+            flat_get_driver.jit_merge_point(shapelen=shapelen,
+                                             base=base,
+                                             basei=basei,
+                                             step=step,
+                                             res=res,
+                                             ri=ri,
+                                            ) 
+            w_val = base.getitem(basei.offset)
+            res.setitem(ri.offset,w_val)
+            basei = basei.next_skip_x(shapelen, step)
+            ri = ri.next(shapelen)
+        return res
+
+    def descr_setitem(self, space, w_idx, w_value):
+        if not (space.isinstance_w(w_idx, space.w_int) or
+            space.isinstance_w(w_idx, space.w_slice)):
+            raise OperationError(space.w_IndexError,
+                                 space.wrap('unsupported iterator index'))
+        base = self.base
+        start, stop, step, lngth = space.decode_index4(w_idx, base.size)
+        arr = convert_to_array(space, w_value)
+        ai = 0
+        basei = ViewIterator(base.start, base.strides,
+                               base.backstrides,base.shape)
+        shapelen = len(base.shape)
+        basei = basei.next_skip_x(shapelen, start)
+        while lngth > 0:
+            flat_set_driver.jit_merge_point(shapelen=shapelen,
+                                             basei=basei,
+                                             base=base,
+                                             step=step,
+                                             arr=arr,
+                                             ai=ai,
+                                             lngth=lngth,
+                                            ) 
+            v = arr.getitem(ai).convert_to(base.dtype)
+            base.setitem(basei.offset, v)
+            # need to repeat input values until all assignments are done
+            ai = (ai + 1) % arr.size
+            basei = basei.next_skip_x(shapelen, step)
+            lngth -= 1
+
+    def create_sig(self):
+        return signature.FlatSignature(self.base.dtype)
+
+    def descr_base(self, space):
+        return space.wrap(self.base)
+
 W_FlatIterator.typedef = TypeDef(
     'flatiter',
+    #__array__  = #MISSING
+    __iter__ = interp2app(W_FlatIterator.descr_iter),
+    __getitem__ = interp2app(W_FlatIterator.descr_getitem),
+    __setitem__ = interp2app(W_FlatIterator.descr_setitem),
+    __eq__ = interp2app(BaseArray.descr_eq),
+    __ne__ = interp2app(BaseArray.descr_ne),
+    __lt__ = interp2app(BaseArray.descr_lt),
+    __le__ = interp2app(BaseArray.descr_le),
+    __gt__ = interp2app(BaseArray.descr_gt),
+    __ge__ = interp2app(BaseArray.descr_ge),
+    #__sizeof__ #MISSING
+    base = GetSetProperty(W_FlatIterator.descr_base),
+    index = GetSetProperty(W_FlatIterator.descr_index),
+    coords = GetSetProperty(W_FlatIterator.descr_coords),
     next = interp2app(W_FlatIterator.descr_next),
-    __iter__ = interp2app(W_FlatIterator.descr_iter),
+
 )
 W_FlatIterator.acceptable_as_base_class = False
 
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -1,14 +1,15 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_boxes, interp_dtype
-from pypy.module.micronumpy.signature import ReduceSignature,\
-     find_sig, new_printable_location, AxisReduceSignature, ScalarSignature
+from pypy.module.micronumpy import interp_boxes, interp_dtype, support
+from pypy.module.micronumpy.signature import (ReduceSignature, find_sig,
+    new_printable_location, AxisReduceSignature, ScalarSignature)
 from pypy.rlib import jit
 from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.tool.sourcetools import func_with_new_name
 
+
 reduce_driver = jit.JitDriver(
     greens=['shapelen', "sig"],
     virtualizables=["frame"],
@@ -30,12 +31,14 @@
     _attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
     _immutable_fields_ = ["promote_to_float", "promote_bools", "name"]
 
-    def __init__(self, name, promote_to_float, promote_bools, identity):
+    def __init__(self, name, promote_to_float, promote_bools, identity,
+                 int_only):
         self.name = name
         self.promote_to_float = promote_to_float
         self.promote_bools = promote_bools
 
         self.identity = identity
+        self.int_only = int_only
 
     def descr_repr(self, space):
         return space.wrap("<ufunc '%s'>" % self.name)
@@ -46,19 +49,31 @@
         return self.identity
 
     def descr_call(self, space, __args__):
-        if __args__.keywords or len(__args__.arguments_w) < self.argcount:
+        args_w, kwds_w = __args__.unpack()
+        # it occurs to me that we don't support any datatypes that
+        # require casting, change it later when we do
+        kwds_w.pop('casting', None)
+        w_subok = kwds_w.pop('subok', None)
+        w_out = kwds_w.pop('out', space.w_None)
+        if ((w_subok is not None and space.is_true(w_subok)) or
+            not space.is_w(w_out, space.w_None)):
+            raise OperationError(space.w_NotImplementedError,
+                                 space.wrap("parameters unsupported"))
+        if kwds_w or len(args_w) < self.argcount:
             raise OperationError(space.w_ValueError,
                 space.wrap("invalid number of arguments")
             )
-        elif len(__args__.arguments_w) > self.argcount:
+        elif len(args_w) > self.argcount:
             # The extra arguments should actually be the output array, but we
             # don't support that yet.
             raise OperationError(space.w_TypeError,
                 space.wrap("invalid number of arguments")
             )
-        return self.call(space, __args__.arguments_w)
+        return self.call(space, args_w)
 
-    def descr_reduce(self, space, w_obj, w_dim=0):
+    @unwrap_spec(skipna=bool, keepdims=bool)
+    def descr_reduce(self, space, w_obj, w_axis=NoneNotWrapped, w_dtype=None,
+                     skipna=False, keepdims=False, w_out=None):
         """reduce(...)
         reduce(a, axis=0)
 
@@ -111,15 +126,24 @@
         array([[ 1,  5],
                [ 9, 13]])
         """
-        return self.reduce(space, w_obj, False, False, w_dim)
+        if not space.is_w(w_out, space.w_None):
+            raise OperationError(space.w_NotImplementedError, space.wrap(
+                "out not supported"))
+        if w_axis is None:
+            axis = 0
+        elif space.is_w(w_axis, space.w_None):
+            axis = -1
+        else:
+            axis = space.int_w(w_axis)
+        return self.reduce(space, w_obj, False, False, axis, keepdims)
 
-    def reduce(self, space, w_obj, multidim, promote_to_largest, w_dim):
+    def reduce(self, space, w_obj, multidim, promote_to_largest, dim,
+               keepdims=False):
         from pypy.module.micronumpy.interp_numarray import convert_to_array, \
                                                            Scalar
         if self.argcount != 2:
             raise OperationError(space.w_ValueError, space.wrap("reduce only "
                 "supported for binary functions"))
-        dim = space.int_w(w_dim)
         assert isinstance(self, W_Ufunc2)
         obj = convert_to_array(space, w_obj)
         if dim >= len(obj.shape):
@@ -140,7 +164,7 @@
             raise operationerrfmt(space.w_ValueError, "zero-size array to "
                     "%s.reduce without identity", self.name)
         if shapelen > 1 and dim >= 0:
-            res = self.do_axis_reduce(obj, dtype, dim)
+            res = self.do_axis_reduce(obj, dtype, dim, keepdims)
             return space.wrap(res)
         scalarsig = ScalarSignature(dtype)
         sig = find_sig(ReduceSignature(self.func, self.name, dtype,
@@ -154,15 +178,15 @@
             value = self.identity.convert_to(dtype)
         return self.reduce_loop(shapelen, sig, frame, value, obj, dtype)
 
-    def do_axis_reduce(self, obj, dtype, dim):
+    def do_axis_reduce(self, obj, dtype, dim, keepdims):
         from pypy.module.micronumpy.interp_numarray import AxisReduce,\
              W_NDimArray
-        
-        shape = obj.shape[0:dim] + obj.shape[dim + 1:len(obj.shape)]
-        size = 1
-        for s in shape:
-            size *= s
-        result = W_NDimArray(size, shape, dtype)
+
+        if keepdims:
+            shape = obj.shape[:dim] + [1] + obj.shape[dim + 1:]
+        else:
+            shape = obj.shape[:dim] + obj.shape[dim + 1:]
+        result = W_NDimArray(support.product(shape), shape, dtype)
         rightsig = obj.create_sig()
         # note - this is just a wrapper so signature can fetch
         #        both left and right, nothing more, especially
@@ -224,10 +248,12 @@
     _immutable_fields_ = ["func", "name"]
 
     def __init__(self, func, name, promote_to_float=False, promote_bools=False,
-        identity=None):
+        identity=None, bool_result=False, int_only=False):
 
-        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
+        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity,
+                         int_only)
         self.func = func
+        self.bool_result = bool_result
 
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call1,
@@ -235,15 +261,19 @@
 
         [w_obj] = args_w
         w_obj = convert_to_array(space, w_obj)
-        res_dtype = find_unaryop_result_dtype(space,
-            w_obj.find_dtype(),
-            promote_to_float=self.promote_to_float,
-            promote_bools=self.promote_bools,
-        )
+        calc_dtype = find_unaryop_result_dtype(space,
+                                  w_obj.find_dtype(),
+                                  promote_to_float=self.promote_to_float,
+                                  promote_bools=self.promote_bools)
+        if self.bool_result:
+            res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
+        else:
+            res_dtype = calc_dtype
         if isinstance(w_obj, Scalar):
-            return self.func(res_dtype, w_obj.value.convert_to(res_dtype))
+            return space.wrap(self.func(calc_dtype, w_obj.value.convert_to(calc_dtype)))
 
-        w_res = Call1(self.func, self.name, w_obj.shape, res_dtype, w_obj)
+        w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype, res_dtype,
+                      w_obj)
         w_obj.add_invalidates(w_res)
         return w_res
 
@@ -255,10 +285,10 @@
     def __init__(self, func, name, promote_to_float=False, promote_bools=False,
         identity=None, comparison_func=False, int_only=False):
 
-        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
+        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity,
+                         int_only)
         self.func = func
         self.comparison_func = comparison_func
-        self.int_only = int_only
 
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call2,
@@ -278,10 +308,10 @@
         else:
             res_dtype = calc_dtype
         if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
-            return self.func(calc_dtype,
+            return space.wrap(self.func(calc_dtype,
                 w_lhs.value.convert_to(calc_dtype),
                 w_rhs.value.convert_to(calc_dtype)
-            )
+            ))
 
         new_shape = shape_agreement(space, w_lhs.shape, w_rhs.shape)
         w_res = Call2(self.func, self.name,
@@ -409,12 +439,16 @@
     return interp_dtype.get_dtype_cache(space).w_float64dtype
 
 
-def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
+def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func,
+                       bool_result):
+    dtype_cache = interp_dtype.get_dtype_cache(space)
     if argcount == 1:
         def impl(res_dtype, value):
-            return getattr(res_dtype.itemtype, op_name)(value)
+            res = getattr(res_dtype.itemtype, op_name)(value)
+            if bool_result:
+                return dtype_cache.w_booldtype.box(res)
+            return res
     elif argcount == 2:
-        dtype_cache = interp_dtype.get_dtype_cache(space)
         def impl(res_dtype, lvalue, rvalue):
             res = getattr(res_dtype.itemtype, op_name)(lvalue, rvalue)
             if comparison_func:
@@ -433,7 +467,9 @@
                                                'int_only': True}),
             ("bitwise_or", "bitwise_or", 2, {"identity": 0,
                                              'int_only': True}),
+            ("invert", "invert", 1, {"int_only": True}),
             ("divide", "div", 2, {"promote_bools": True}),
+            ("true_divide", "div", 2, {"promote_to_float": True}),
             ("mod", "mod", 2, {"promote_bools": True}),
             ("power", "pow", 2, {"promote_bools": True}),
 
@@ -443,6 +479,8 @@
             ("less_equal", "le", 2, {"comparison_func": True}),
             ("greater", "gt", 2, {"comparison_func": True}),
             ("greater_equal", "ge", 2, {"comparison_func": True}),
+            ("isnan", "isnan", 1, {"bool_result": True}),
+            ("isinf", "isinf", 1, {"bool_result": True}),
 
             ("maximum", "max", 2),
             ("minimum", "min", 2),
@@ -485,6 +523,7 @@
 
         func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
             comparison_func=extra_kwargs.get("comparison_func", False),
+            bool_result=extra_kwargs.get("bool_result", False),
         )
         if argcount == 1:
             ufunc = W_Ufunc1(func, ufunc_name, **extra_kwargs)
@@ -494,3 +533,4 @@
 
 def get(space):
     return space.fromcache(UfuncState)
+
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -224,6 +224,18 @@
         return ViewIterator(arr.start, arr.strides, arr.backstrides,
                             arr.shape).apply_transformations(arr, transforms)
 
+class FlatSignature(ViewSignature):
+    def debug_repr(self):
+        return 'Flat'
+
+    def allocate_iter(self, arr, transforms):
+        from pypy.module.micronumpy.interp_numarray import W_FlatIterator
+        assert isinstance(arr, W_FlatIterator)
+        return ViewIterator(arr.base.start, arr.base.strides, 
+                    arr.base.backstrides,
+                    arr.base.shape).apply_transformations(arr.base,
+                                                         transforms)
+
 class VirtualSliceSignature(Signature):
     def __init__(self, child):
         self.child = child
@@ -293,8 +305,8 @@
     def eval(self, frame, arr):
         from pypy.module.micronumpy.interp_numarray import Call1
         assert isinstance(arr, Call1)
-        v = self.child.eval(frame, arr.values).convert_to(arr.res_dtype)
-        return self.unfunc(arr.res_dtype, v)
+        v = self.child.eval(frame, arr.values).convert_to(arr.calc_dtype)
+        return self.unfunc(arr.calc_dtype, v)
 
 class Call2(Signature):
     _immutable_fields_ = ['binfunc', 'name', 'calc_dtype', 'left', 'right']
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -1,5 +1,5 @@
 from pypy.rlib import jit
-
+from pypy.interpreter.error import OperationError
 
 @jit.look_inside_iff(lambda shape, start, strides, backstrides, chunks:
     jit.isconstant(len(chunks))
@@ -37,3 +37,196 @@
     rstrides = [0] * (len(res_shape) - len(orig_shape)) + rstrides
     rbackstrides = [0] * (len(res_shape) - len(orig_shape)) + rbackstrides
     return rstrides, rbackstrides
+
+def find_shape_and_elems(space, w_iterable):
+    shape = [space.len_w(w_iterable)]
+    batch = space.listview(w_iterable)
+    while True:
+        new_batch = []
+        if not batch:
+            return shape, []
+        if not space.issequence_w(batch[0]):
+            for elem in batch:
+                if space.issequence_w(elem):
+                    raise OperationError(space.w_ValueError, space.wrap(
+                        "setting an array element with a sequence"))
+            return shape, batch
+        size = space.len_w(batch[0])
+        for w_elem in batch:
+            if not space.issequence_w(w_elem) or space.len_w(w_elem) != size:
+                raise OperationError(space.w_ValueError, space.wrap(
+                    "setting an array element with a sequence"))
+            new_batch += space.listview(w_elem)
+        shape.append(size)
+        batch = new_batch
+
+def to_coords(space, shape, size, order, w_item_or_slice):
+    '''Returns a start coord, step, and length.
+    '''
+    start = lngth = step = 0
+    if not (space.isinstance_w(w_item_or_slice, space.w_int) or
+        space.isinstance_w(w_item_or_slice, space.w_slice)):
+        raise OperationError(space.w_IndexError,
+                             space.wrap('unsupported iterator index'))
+            
+    start, stop, step, lngth = space.decode_index4(w_item_or_slice, size)
+        
+    coords = [0] * len(shape)
+    i = start
+    if order == 'C':
+        for s in range(len(shape) -1, -1, -1):
+            coords[s] = i % shape[s]
+            i //= shape[s]
+    else:
+        for s in range(len(shape)):
+            coords[s] = i % shape[s]
+            i //= shape[s]
+    return coords, step, lngth
+
+def shape_agreement(space, shape1, shape2):
+    ret = _shape_agreement(shape1, shape2)
+    if len(ret) < max(len(shape1), len(shape2)):
+        raise OperationError(space.w_ValueError,
+            space.wrap("operands could not be broadcast together with shapes (%s) (%s)" % (
+                ",".join([str(x) for x in shape1]),
+                ",".join([str(x) for x in shape2]),
+            ))
+        )
+    return ret
+
+def _shape_agreement(shape1, shape2):
+    """ Checks agreement about two shapes with respect to broadcasting. Returns
+    the resulting shape.
+    """
+    lshift = 0
+    rshift = 0
+    if len(shape1) > len(shape2):
+        m = len(shape1)
+        n = len(shape2)
+        rshift = len(shape2) - len(shape1)
+        remainder = shape1
+    else:
+        m = len(shape2)
+        n = len(shape1)
+        lshift = len(shape1) - len(shape2)
+        remainder = shape2
+    endshape = [0] * m
+    indices1 = [True] * m
+    indices2 = [True] * m
+    for i in range(m - 1, m - n - 1, -1):
+        left = shape1[i + lshift]
+        right = shape2[i + rshift]
+        if left == right:
+            endshape[i] = left
+        elif left == 1:
+            endshape[i] = right
+            indices1[i + lshift] = False
+        elif right == 1:
+            endshape[i] = left
+            indices2[i + rshift] = False
+        else:
+            return []
+            #raise OperationError(space.w_ValueError, space.wrap(
+            #    "frames are not aligned"))
+    for i in range(m - n):
+        endshape[i] = remainder[i]
+    return endshape
+
+def get_shape_from_iterable(space, old_size, w_iterable):
+    new_size = 0
+    new_shape = []
+    if space.isinstance_w(w_iterable, space.w_int):
+        new_size = space.int_w(w_iterable)
+        if new_size < 0:
+            new_size = old_size
+        new_shape = [new_size]
+    else:
+        neg_dim = -1
+        batch = space.listview(w_iterable)
+        new_size = 1
+        if len(batch) < 1:
+            if old_size == 1:
+                # Scalars can have an empty size.
+                new_size = 1
+            else:
+                new_size = 0
+        new_shape = []
+        i = 0
+        for elem in batch:
+            s = space.int_w(elem)
+            if s < 0:
+                if neg_dim >= 0:
+                    raise OperationError(space.w_ValueError, space.wrap(
+                             "can only specify one unknown dimension"))
+                s = 1
+                neg_dim = i
+            new_size *= s
+            new_shape.append(s)
+            i += 1
+        if neg_dim >= 0:
+            new_shape[neg_dim] = old_size / new_size
+            new_size *= new_shape[neg_dim]
+    if new_size != old_size:
+        raise OperationError(space.w_ValueError,
+                space.wrap("total size of new array must be unchanged"))
+    return new_shape
+
+# Recalculating strides. Find the steps that the iteration does for each
+# dimension, given the stride and shape. Then try to create a new stride that
+# fits the new shape, using those steps. If there is a shape/step mismatch
+# (meaning that the realignment of elements crosses from one step into another)
+# return None so that the caller can raise an exception.
+def calc_new_strides(new_shape, old_shape, old_strides, order):
+    # Return the proper strides for new_shape, or None if the mapping crosses
+    # stepping boundaries
+
+    # Assumes that prod(old_shape) == prod(new_shape), len(old_shape) > 1, and
+    # len(new_shape) > 0
+    steps = []
+    last_step = 1
+    oldI = 0
+    new_strides = []
+    if order == 'F':
+        for i in range(len(old_shape)):
+            steps.append(old_strides[i] / last_step)
+            last_step *= old_shape[i]
+        cur_step = steps[0]
+        n_new_elems_used = 1
+        n_old_elems_to_use = old_shape[0]
+        for s in new_shape:
+            new_strides.append(cur_step * n_new_elems_used)
+            n_new_elems_used *= s
+            while n_new_elems_used > n_old_elems_to_use:
+                oldI += 1
+                if steps[oldI] != steps[oldI - 1]:
+                    return None
+                n_old_elems_to_use *= old_shape[oldI]
+            if n_new_elems_used == n_old_elems_to_use:
+                oldI += 1
+                if oldI < len(old_shape):
+                    cur_step = steps[oldI]
+                    n_old_elems_to_use *= old_shape[oldI]
+    elif order == 'C':
+        for i in range(len(old_shape) - 1, -1, -1):
+            steps.insert(0, old_strides[i] / last_step)
+            last_step *= old_shape[i]
+        cur_step = steps[-1]
+        n_new_elems_used = 1
+        oldI = -1
+        n_old_elems_to_use = old_shape[-1]
+        for i in range(len(new_shape) - 1, -1, -1):
+            s = new_shape[i]
+            new_strides.insert(0, cur_step * n_new_elems_used)
+            n_new_elems_used *= s
+            while n_new_elems_used > n_old_elems_to_use:
+                oldI -= 1
+                if steps[oldI] != steps[oldI + 1]:
+                    return None
+                n_old_elems_to_use *= old_shape[oldI]
+            if n_new_elems_used == n_old_elems_to_use:
+                oldI -= 1
+                if oldI >= -len(old_shape):
+                    cur_step = steps[oldI]
+                    n_old_elems_to_use *= old_shape[oldI]
+    assert len(new_strides) == len(new_shape)
+    return new_strides
diff --git a/pypy/module/micronumpy/support.py b/pypy/module/micronumpy/support.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/support.py
@@ -0,0 +1,5 @@
+def product(s):
+    i = 1
+    for x in s:
+        i *= x
+    return i
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -3,9 +3,17 @@
 from pypy.module.micronumpy.interp_numarray import W_NDimArray, Scalar
 from pypy.module.micronumpy.interp_ufuncs import (find_binop_result_dtype,
         find_unaryop_result_dtype)
+from pypy.module.micronumpy.interp_boxes import W_Float64Box
+from pypy.conftest import option
+import sys
 
 class BaseNumpyAppTest(object):
     def setup_class(cls):
+        if option.runappdirect:
+            if '__pypy__' not in sys.builtin_module_names:
+                import numpy
+                sys.modules['numpypy'] = numpy
+                sys.modules['_numpypy'] = numpy
         cls.space = gettestobjspace(usemodules=['micronumpy'])
 
 class TestSignature(object):
@@ -16,7 +24,7 @@
         ar = W_NDimArray(10, [10], dtype=float64_dtype)
         ar2 = W_NDimArray(10, [10], dtype=float64_dtype)
         v1 = ar.descr_add(space, ar)
-        v2 = ar.descr_add(space, Scalar(float64_dtype, 2.0))
+        v2 = ar.descr_add(space, Scalar(float64_dtype, W_Float64Box(2.0)))
         sig1 = v1.find_sig()
         sig2 = v2.find_sig()
         assert v1 is not v2
@@ -26,7 +34,7 @@
         sig1b = ar2.descr_add(space, ar).find_sig()
         assert sig1b.left.array_no != sig1b.right.array_no
         assert sig1b is not sig1
-        v3 = ar.descr_add(space, Scalar(float64_dtype, 1.0))
+        v3 = ar.descr_add(space, Scalar(float64_dtype, W_Float64Box(1.0)))
         sig3 = v3.find_sig()
         assert sig2 is sig3
         v4 = ar.descr_add(space, ar)
diff --git a/pypy/module/micronumpy/test/test_compile.py b/pypy/module/micronumpy/test/test_compile.py
--- a/pypy/module/micronumpy/test/test_compile.py
+++ b/pypy/module/micronumpy/test/test_compile.py
@@ -245,3 +245,19 @@
         a -> 3
         """)
         assert interp.results[0].value == 11
+
+    def test_flat_iter(self):
+        interp = self.run('''
+        a = |30|
+        b = flat(a)
+        b -> 3
+        ''')
+        assert interp.results[0].value == 3
+
+    def test_take(self):
+        interp = self.run("""
+        a = |10|
+        b = take(a, [1, 1, 3, 2])
+        b -> 2
+        """)
+        assert interp.results[0].value == 3
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -11,8 +11,17 @@
         assert dtype('int8').num == 1
         assert dtype(d) is d
         assert dtype(None) is dtype(float)
+        assert dtype('int8').name == 'int8'
         raises(TypeError, dtype, 1042)
 
+    def test_dtype_eq(self):
+        from _numpypy import dtype
+
+        assert dtype("int8") == "int8"
+        assert "int8" == dtype("int8")
+        raises(TypeError, lambda: dtype("int8") == 3)
+        assert dtype(bool) == bool
+
     def test_dtype_with_types(self):
         from _numpypy import dtype
 
@@ -30,7 +39,7 @@
     def test_repr_str(self):
         from _numpypy import dtype
 
-        assert repr(dtype) == "<type 'numpypy.dtype'>"
+        assert '.dtype' in repr(dtype)
         d = dtype('?')
         assert repr(d) == "dtype('bool')"
         assert str(d) == "bool"
@@ -376,3 +385,19 @@
         b = X(10)
         assert type(b) is X
         assert b.m() == 12
+
+    def test_long_as_index(self):
+        skip("waiting for removal of multimethods of __index__")
+        from _numpypy import int_
+        assert (1, 2, 3)[int_(1)] == 2
+
+    def test_int(self):
+        import sys
+        from _numpypy import int32, int64, int_
+        assert issubclass(int_, int)
+        if sys.maxint == (1<<31) - 1:
+            assert issubclass(int32, int)
+            assert int_ is int32
+        else:
+            assert issubclass(int64, int)
+            assert int_ is int64
diff --git a/pypy/module/micronumpy/test/test_iter.py b/pypy/module/micronumpy/test/test_iter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_iter.py
@@ -0,0 +1,88 @@
+from pypy.module.micronumpy.interp_iter import ViewIterator
+
+class TestIterDirect(object):
+    def test_C_viewiterator(self):
+        #Let's get started, simple iteration in C order with
+        #contiguous layout => strides[-1] is 1
+        start = 0
+        shape = [3, 5] 
+        strides = [5, 1]
+        backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
+        assert backstrides == [10, 4]
+        i = ViewIterator(start, strides, backstrides, shape)
+        i = i.next(2)
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 3
+        assert not i.done()
+        assert i.indices == [0,3]
+        #cause a dimension overflow
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 5
+        assert i.indices == [1,0]
+
+        #Now what happens if the array is transposed? strides[-1] != 1
+        # therefore layout is non-contiguous
+        strides = [1, 3]
+        backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
+        assert backstrides == [2, 12]
+        i = ViewIterator(start, strides, backstrides, shape)
+        i = i.next(2)
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 9
+        assert not i.done()
+        assert i.indices == [0,3]
+        #cause a dimension overflow
+        i = i.next(2)
+        i = i.next(2)
+        assert i.offset == 1
+        assert i.indices == [1,0]
+
+    def test_C_viewiterator_step(self):
+        #iteration in C order with #contiguous layout => strides[-1] is 1
+        #skip less than the shape
+        start = 0
+        shape = [3, 5] 
+        strides = [5, 1]
+        backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
+        assert backstrides == [10, 4]
+        i = ViewIterator(start, strides, backstrides, shape)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        assert i.offset == 6
+        assert not i.done()
+        assert i.indices == [1,1]
+        #And for some big skips
+        i = i.next_skip_x(2,5)
+        assert i.offset == 11
+        assert i.indices == [2,1]
+        i = i.next_skip_x(2,5)
+        # Note: the offset does not overflow but recycles,
+        # this is good for broadcast
+        assert i.offset == 1
+        assert i.indices == [0,1]
+        assert i.done()
+
+        #Now what happens if the array is transposed? strides[-1] != 1
+        # therefore layout is non-contiguous
+        strides = [1, 3]
+        backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
+        assert backstrides == [2, 12]
+        i = ViewIterator(start, strides, backstrides, shape)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        i = i.next_skip_x(2,2)
+        assert i.offset == 4
+        assert i.indices == [1,1]
+        assert not i.done()
+        i = i.next_skip_x(2,5)
+        assert i.offset == 5
+        assert i.indices == [2,1]
+        assert not i.done()
+        i = i.next_skip_x(2,5)
+        assert i.indices == [0,1]
+        assert i.offset == 3
+        assert i.done()
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -167,6 +167,23 @@
         assert calc_new_strides([1, 1, 105, 1, 1], [7, 15], [1, 7],'F') == \
                                     [1, 1, 1, 105, 105]
 
+    def test_to_coords(self):
+        from pypy.module.micronumpy.strides import to_coords
+
+        def _to_coords(index, order):
+            return to_coords(self.space, [2, 3, 4], 24, order,
+                             self.space.wrap(index))[0]
+        
+        assert _to_coords(0, 'C') == [0, 0, 0]
+        assert _to_coords(1, 'C') == [0, 0, 1]
+        assert _to_coords(-1, 'C') == [1, 2, 3]
+        assert _to_coords(5, 'C') == [0, 1, 1]
+        assert _to_coords(13, 'C') == [1, 0, 1]
+        assert _to_coords(0, 'F') == [0, 0, 0]
+        assert _to_coords(1, 'F') == [1, 0, 0]
+        assert _to_coords(-1, 'F') == [1, 2, 3]
+        assert _to_coords(5, 'F') == [1, 2, 0]
+        assert _to_coords(13, 'F') == [1, 0, 2]
 
 class AppTestNumArray(BaseNumpyAppTest):
     def test_ndarray(self):
@@ -211,6 +228,7 @@
         # And check that changes stick.
         a[13] = 5.3
         assert a[13] == 5.3
+        assert zeros(()).shape == ()
 
     def test_size(self):
         from _numpypy import array
@@ -254,6 +272,7 @@
         b = a[::2]
         c = b.copy()
         assert (c == b).all()
+        assert ((a + a).copy() == (a + a)).all()
 
         a = arange(15).reshape(5,3)
         b = a.copy()
@@ -283,6 +302,12 @@
         for i in xrange(5):
             assert a[i] == b[i]
 
+    def test_getitem_nd(self):
+        from _numpypy import arange
+        a = arange(15).reshape(3, 5)
+        assert a[1, 3] == 8
+        assert a.T[1, 2] == 11 
+
     def test_setitem(self):
         from _numpypy import array
         a = array(range(5))
@@ -370,6 +395,7 @@
         assert b.shape == (5,)
         c = a[:3]
         assert c.shape == (3,)
+        assert array([]).shape == (0,)
 
     def test_set_shape(self):
         from _numpypy import array, zeros
@@ -405,6 +431,7 @@
         assert (a == [1000, 1, 2, 3, 1000, 5, 6, 7, 1000, 9, 10, 11]).all()
         a = zeros((4, 2, 3))
         a.shape = (12, 2)
+        (a + a).reshape(2, 12) # assert did not explode
 
     def test_slice_reshape(self):
         from _numpypy import zeros, arange
@@ -448,6 +475,13 @@
         y = z.reshape(4, 3, 8)
         assert y.shape == (4, 3, 8)
 
+    def test_scalar_reshape(self):
+        from numpypy import array
+        a = array(3)
+        assert a.reshape([1, 1]).shape == (1, 1)
+        assert a.reshape([1]).shape == (1,)
+        raises(ValueError, "a.reshape(3)")
+
     def test_add(self):
         from _numpypy import array
         a = array(range(5))
@@ -956,7 +990,7 @@
         assert debug_repr(a + a) == 'Call2(add, Array, Array)'
         assert debug_repr(a[::2]) == 'Slice'
         assert debug_repr(a + 2) == 'Call2(add, Array, Scalar)'
-        assert debug_repr(a + a.flat) == 'Call2(add, Array, Slice)'
+        assert debug_repr(a + a.flat) == 'Call2(add, Array, Flat)'
         assert debug_repr(sin(a)) == 'Call1(sin, Array)'
 
         b = a + a
@@ -1036,8 +1070,42 @@
         assert a.var() == 0.0
         a = arange(10).reshape(5, 2)
         assert a.var() == 8.25
-        #assert (a.var(0) == [8, 8]).all()
-        #assert (a.var(1) == [.25] * 5).all()
+        assert (a.var(0) == [8, 8]).all()
+        assert (a.var(1) == [.25] * 5).all()
+
+    def test_concatenate(self):
+        from numpypy import array, concatenate, dtype
+        a1 = array([0,1,2])
+        a2 = array([3,4,5])
+        a = concatenate((a1, a2))
+        assert len(a) == 6
+        assert (a == [0,1,2,3,4,5]).all()
+        assert a.dtype is dtype(int)
+        b1 = array([[1, 2], [3, 4]])
+        b2 = array([[5, 6]])
+        b = concatenate((b1, b2), axis=0)
+        assert (b == [[1, 2],[3, 4],[5, 6]]).all()
+        c = concatenate((b1, b2.T), axis=1)
+        assert (c == [[1, 2, 5],[3, 4, 6]]).all()
+        d = concatenate(([0],[1]))
+        assert (d == [0,1]).all()
+        e1 = array([[0,1],[2,3]])
+        e = concatenate(e1)
+        assert (e == [0,1,2,3]).all()
+        f1 = array([0,1])
+        f = concatenate((f1, [2], f1, [7]))
+        assert (f == [0,1,2,0,1,7]).all()
+        
+        bad_axis = raises(ValueError, concatenate, (a1,a2), axis=1)
+        assert str(bad_axis.value) == "bad axis argument"
+        
+        concat_zero = raises(ValueError, concatenate, ())
+        assert str(concat_zero.value) == \
+            "concatenation of zero-length sequences is impossible"
+        
+        dims_disagree = raises(ValueError, concatenate, (a1, b1), axis=0)
+        assert str(dims_disagree.value) == \
+            "array dimensions must agree except for axis being concatenated"
 
     def test_std(self):
         from _numpypy import array
@@ -1049,6 +1117,13 @@
     def test_flatten(self):
         from _numpypy import array
 
+        assert array(3).flatten().shape == (1,)
+        a = array([[1, 2], [3, 4]])
+        b = a.flatten()
+        c = a.ravel()
+        a[0, 0] = 15
+        assert b[0] == 1
+        assert c[0] == 15
         a = array([[1, 2, 3], [4, 5, 6]])
         assert (a.flatten() == [1, 2, 3, 4, 5, 6]).all()
         a = array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
@@ -1062,7 +1137,6 @@
         a = array([[1, 2], [3, 4]])
         assert (a.T.flatten() == [1, 3, 2, 4]).all()
 
-
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
         import _numpypy
@@ -1077,7 +1151,7 @@
         assert _numpypy.array([[1], [2], [3]]).shape == (3, 1)
         assert len(_numpypy.zeros((3, 1, 2))) == 3
         raises(TypeError, len, _numpypy.zeros(()))
-        raises(ValueError, _numpypy.array, [[1, 2], 3])
+        raises(ValueError, _numpypy.array, [[1, 2], 3], dtype=float)
 
     def test_getsetitem(self):
         import _numpypy
@@ -1292,7 +1366,7 @@
         assert(b[:, 0] == a[0, :]).all()
 
     def test_flatiter(self):
-        from _numpypy import array, flatiter
+        from _numpypy import array, flatiter, arange
         a = array([[10, 30], [40, 60]])
         f_iter = a.flat
         assert f_iter.next() == 10
@@ -1305,6 +1379,9 @@
         for k in a.flat:
             s += k
         assert s == 140
+        a = arange(10).reshape(5, 2)
+        raises(IndexError, 'a.flat[(1, 2)]')
+        assert a.flat.base is a
 
     def test_flatiter_array_conv(self):
         from _numpypy import array, dot
@@ -1316,6 +1393,75 @@
         a = ones((2, 2))
         assert list(((a + a).flat)) == [2, 2, 2, 2]
 
+    def test_flatiter_getitem(self):
+        from _numpypy import arange
+        a = arange(10)
+        assert a.flat[3] == 3
+        assert a[2:].flat[3] == 5
+        assert (a + a).flat[3] == 6
+        assert a[::2].flat[3] == 6
+        assert a.reshape(2,5).flat[3] == 3
+        b = a.reshape(2,5).flat
+        b.next()
+        b.next()
+        b.next()
+        assert b[3] == 3
+        assert (b[::3] == [0, 3, 6, 9]).all()
+        assert (b[2::5] == [2, 7]).all()
+        assert b[-2] == 8
+        raises(IndexError, "b[11]")
+        raises(IndexError, "b[-11]")
+        raises(IndexError, 'b[0, 1]')
+        assert b.index == 3
+        assert b.coords == (0,3)
+
+    def test_flatiter_setitem(self):
+        from _numpypy import arange, array
+        a = arange(12).reshape(3,4)
+        b = a.T.flat
+        b[6::2] = [-1, -2]
+        assert (a == [[0, 1, -1, 3], [4, 5, 6, -1], [8, 9, -2, 11]]).all()
+        b[0:2] = [[[100]]]
+        assert(a[0,0] == 100)
+        assert(a[1,0] == 100)
+        raises(IndexError, 'b[array([10, 11])] == [-20, -40]')
+
+    def test_flatiter_ops(self):
+        from _numpypy import arange, array
+        a = arange(12).reshape(3,4)
+        b = a.T.flat
+        assert (b == [0,  4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11]).all()
+        assert not (b != [0,  4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11]).any()
+        assert ((b >= range(12)) == [True, True, True,False, True, True, 
+                             False, False, True, False, False, True]).all()
+        assert ((b < range(12)) != [True, True, True,False, True, True, 
+                             False, False, True, False, False, True]).all()
+        assert ((b <= range(12)) != [False, True, True,False, True, True, 
+                            False, False, True, False, False, False]).all()
+        assert ((b > range(12)) == [False, True, True,False, True, True, 
+                            False, False, True, False, False, False]).all()
+    def test_flatiter_view(self):
+        from _numpypy import arange
+        a = arange(10).reshape(5, 2)
+        #no == yet.
+        # a[::2].flat == [0, 1, 4, 5, 8, 9]
+        isequal = True
+        for y,z in zip(a[::2].flat, [0, 1, 4, 5, 8, 9]):
+            if y != z:
+                isequal = False
+        assert isequal == True
+
+    def test_flatiter_transpose(self):
+        from _numpypy import arange
+        a = arange(10).reshape(2,5).T
+        b = a.flat
+        assert (b[:5] == [0, 5, 1, 6, 2]).all()
+        b.next()
+        b.next()
+        b.next()
+        assert b.index == 3
+        assert b.coords == (1,1)
+
     def test_slice_copy(self):
         from _numpypy import zeros
         a = zeros((10, 10))
@@ -1381,12 +1527,61 @@
         a[a & 1 == 1] = array([8, 9, 10])
         assert (a == [[0, 8], [2, 9], [4, 10]]).all()
 
+    def test_copy_kwarg(self):
+        from _numpypy import array
+        x = array([1, 2, 3])
+        assert (array(x) == x).all()
+        assert array(x) is not x
+        assert array(x, copy=False) is x
+        assert array(x, copy=True) is not x
+
     def test_isna(self):
         from _numpypy import isna, array
         # XXX for now
         assert not isna(3)
         assert (isna(array([1, 2, 3, 4])) == [False, False, False, False]).all()
 
+    def test_ravel(self):
+        from _numpypy import arange
+        assert (arange(3).ravel() == arange(3)).all()
+        assert (arange(6).reshape(2, 3).ravel() == arange(6)).all()
+        assert (arange(6).reshape(2, 3).T.ravel() == [0, 3, 1, 4, 2, 5]).all()
+
+    def test_take(self):
+        from _numpypy import arange
+        assert (arange(10).take([1, 2, 1, 1]) == [1, 2, 1, 1]).all()
+        raises(IndexError, "arange(3).take([15])")
+        a = arange(6).reshape(2, 3)
+        assert (a.take([1, 0, 3]) == [1, 0, 3]).all()
+        assert ((a + a).take([3]) == [6]).all()
+        a = arange(12).reshape(2, 6)
+        assert (a[:,::2].take([3, 2, 1]) == [6, 4, 2]).all()
+
+    def test_compress(self):
+        from _numpypy import arange
+        a = arange(10)
+        assert (a.compress([True, False, True]) == [0, 2]).all()
+        assert (a.compress([1, 0, 13]) == [0, 2]).all()
+        assert (a.compress([1, 0, 13.5]) == [0, 2]).all()
+        a = arange(10).reshape(2, 5)
+        assert (a.compress([True, False, True]) == [0, 2]).all()
+        raises(IndexError, "a.compress([1] * 100)")
+
+    def test_item(self):
+        from _numpypy import array
+        assert array(3).item() == 3
+        assert type(array(3).item()) is int
+        assert type(array(True).item()) is bool
+        assert type(array(3.5).item()) is float
+        raises((ValueError, IndexError), "array(3).item(15)")
+        raises(ValueError, "array([1, 2, 3]).item()")
+        assert array([3]).item(0) == 3
+        assert type(array([3]).item(0)) is int
+        assert array([1, 2, 3]).item(-1) == 3
+        a = array([1, 2, 3])
+        assert a[::2].item(1) == 3
+        assert (a + a).item(1) == 4
+        raises(ValueError, "array(5).item(1)")
 
 class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
@@ -1498,128 +1693,6 @@
         raises(ValueError, fromstring, "\x01\x02\x03", count=5, dtype=uint8)
 
 
-class AppTestRepr(BaseNumpyAppTest):
-    def test_repr(self):
-        from _numpypy import array, zeros
-        int_size = array(5).dtype.itemsize
-        a = array(range(5), float)
-        assert repr(a) == "array([0.0, 1.0, 2.0, 3.0, 4.0])"
-        a = array([], float)
-        assert repr(a) == "array([], dtype=float64)"
-        a = zeros(1001)
-        assert repr(a) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
-        a = array(range(5), long)
-        if a.dtype.itemsize == int_size:
-            assert repr(a) == "array([0, 1, 2, 3, 4])"
-        else:
-            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int64)"
-        a = array(range(5), 'int32')
-        if a.dtype.itemsize == int_size:
-            assert repr(a) == "array([0, 1, 2, 3, 4])"
-        else:
-            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int32)"
-        a = array([], long)
-        assert repr(a) == "array([], dtype=int64)"
-        a = array([True, False, True, False], "?")
-        assert repr(a) == "array([True, False, True, False], dtype=bool)"
-        a = zeros([])
-        assert repr(a) == "array(0.0)"
-        a = array(0.2)
-        assert repr(a) == "array(0.2)"
-        a = array([2])
-        assert repr(a) == "array([2])"
-
-    def test_repr_multi(self):
-        from _numpypy import arange, zeros, array
-        a = zeros((3, 4))
-        assert repr(a) == '''array([[0.0, 0.0, 0.0, 0.0],
-       [0.0, 0.0, 0.0, 0.0],
-       [0.0, 0.0, 0.0, 0.0]])'''
-        a = zeros((2, 3, 4))
-        assert repr(a) == '''array([[[0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0]],
-
-       [[0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0],
-        [0.0, 0.0, 0.0, 0.0]]])'''
-        a = arange(1002).reshape((2, 501))
-        assert repr(a) == '''array([[0, 1, 2, ..., 498, 499, 500],
-       [501, 502, 503, ..., 999, 1000, 1001]])'''
-        assert repr(a.T) == '''array([[0, 501],
-       [1, 502],
-       [2, 503],
-       ...,
-       [498, 999],
-       [499, 1000],
-       [500, 1001]])'''
-        a = arange(2).reshape((2,1))
-        assert repr(a) == '''array([[0],
-       [1]])'''
-
-    def test_repr_slice(self):
-        from _numpypy import array, zeros
-        a = array(range(5), float)
-        b = a[1::2]
-        assert repr(b) == "array([1.0, 3.0])"
-        a = zeros(2002)
-        b = a[::2]
-        assert repr(b) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
-        a = array((range(5), range(5, 10)), dtype="int16")
-        b = a[1, 2:]
-        assert repr(b) == "array([7, 8, 9], dtype=int16)"
-        # an empty slice prints its shape
-        b = a[2:1, ]
-        assert repr(b) == "array([], shape=(0, 5), dtype=int16)"
-
-    def test_str(self):
-        from _numpypy import array, zeros
-        a = array(range(5), float)
-        assert str(a) == "[0.0 1.0 2.0 3.0 4.0]"
-        assert str((2 * a)[:]) == "[0.0 2.0 4.0 6.0 8.0]"
-        a = zeros(1001)
-        assert str(a) == "[0.0 0.0 0.0 ..., 0.0 0.0 0.0]"
-
-        a = array(range(5), dtype=long)
-        assert str(a) == "[0 1 2 3 4]"
-        a = array([True, False, True, False], dtype="?")
-        assert str(a) == "[True False True False]"
-
-        a = array(range(5), dtype="int8")
-        assert str(a) == "[0 1 2 3 4]"
-
-        a = array(range(5), dtype="int16")
-        assert str(a) == "[0 1 2 3 4]"
-
-        a = array((range(5), range(5, 10)), dtype="int16")
-        assert str(a) == "[[0 1 2 3 4]\n [5 6 7 8 9]]"
-
-        a = array(3, dtype=int)
-        assert str(a) == "3"
-
-        a = zeros((400, 400), dtype=int)
-        assert str(a) == "[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n" \
-           " [0 0 0 ..., 0 0 0]\n ...,\n [0 0 0 ..., 0 0 0]\n" \
-           " [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]"
-        a = zeros((2, 2, 2))
-        r = str(a)
-        assert r == '[[[0.0 0.0]\n  [0.0 0.0]]\n\n [[0.0 0.0]\n  [0.0 0.0]]]'
-
-    def test_str_slice(self):
-        from _numpypy import array, zeros
-        a = array(range(5), float)
-        b = a[1::2]
-        assert str(b) == "[1.0 3.0]"
-        a = zeros(2002)
-        b = a[::2]
-        assert str(b) == "[0.0 0.0 0.0 ..., 0.0 0.0 0.0]"
-        a = array((range(5), range(5, 10)), dtype="int16")
-        b = a[1, 2:]
-        assert str(b) == "[7 8 9]"
-        b = a[2:1, ]
-        assert str(b) == "[]"
-
-
 class AppTestRanges(BaseNumpyAppTest):
     def test_arange(self):
         from _numpypy import arange, array, dtype
@@ -1640,3 +1713,24 @@
         a = arange(0, 0.8, 0.1)
         assert len(a) == 8
         assert arange(False, True, True).dtype is dtype(int)
+
+from pypy.module.micronumpy.appbridge import get_appbridge_cache
+
+class AppTestRepr(BaseNumpyAppTest):
+    def setup_class(cls):
+        BaseNumpyAppTest.setup_class.im_func(cls)
+        cache = get_appbridge_cache(cls.space)
+        cls.old_array_repr = cache.w_array_repr
+        cls.old_array_str = cache.w_array_str
+        cache.w_array_str = None
+        cache.w_array_repr = None
+
+    def test_repr_str(self):
+        from _numpypy import array
+        assert repr(array([1, 2, 3])) == 'array([1, 2, 3])'
+        assert str(array([1, 2, 3])) == 'array([1, 2, 3])'
+
+    def teardown_class(cls):
+        cache = get_appbridge_cache(cls.space)
+        cache.w_array_repr = cls.old_array_repr
+        cache.w_array_str = cls.old_array_str
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -344,7 +344,7 @@
         from _numpypy import sin, add
 
         raises(ValueError, sin.reduce, [1, 2, 3])
-        raises(ValueError, add.reduce, 1)
+        raises((ValueError, TypeError), add.reduce, 1)
 
     def test_reduce_1d(self):
         from _numpypy import add, maximum
@@ -360,6 +360,14 @@
         assert (add.reduce(a, 0) == [12, 15, 18, 21]).all()
         assert (add.reduce(a, 1) == [6.0, 22.0, 38.0]).all()
 
+    def test_reduce_keepdims(self):
+        from _numpypy import add, arange
+        a = arange(12).reshape(3, 4)
+        b = add.reduce(a, 0, keepdims=True)
+        assert b.shape == (1, 4)
+        assert (add.reduce(a, 0, keepdims=True) == [12, 15, 18, 21]).all()
+        
+
     def test_bitwise(self):
         from _numpypy import bitwise_and, bitwise_or, arange, array
         a = arange(6).reshape(2, 3)
@@ -369,6 +377,12 @@
         assert (a | 1 == bitwise_or(a, 1)).all()
         raises(TypeError, 'array([1.0]) & 1')
 
+    def test_unary_bitops(self):
+        from _numpypy import bitwise_not, array
+        a = array([1, 2, 3, 4])
+        assert (~a == [-2, -3, -4, -5]).all()
+        assert (bitwise_not(a) == ~a).all()
+
     def test_comparisons(self):
         import operator
         from _numpypy import equal, not_equal, less, less_equal, greater, greater_equal
@@ -394,3 +408,28 @@
                 (3, 3.5),
             ]:
                 assert ufunc(a, b) == func(a, b)
+
+    def test_count_reduce_items(self):
+        from _numpypy import count_reduce_items, arange
+        a = arange(24).reshape(2, 3, 4)
+        assert count_reduce_items(a) == 24
+        assert count_reduce_items(a, 1) == 3
+        assert count_reduce_items(a, (1, 2)) == 3 * 4
+        
+    def test_true_divide(self):
+        from _numpypy import arange, array, true_divide
+        assert (true_divide(arange(3), array([2, 2, 2])) == array([0, 0.5, 1])).all()
+
+    def test_isnan_isinf(self):
+        from _numpypy import isnan, isinf, float64, array
+        assert isnan(float('nan'))
+        assert isnan(float64(float('nan')))
+        assert not isnan(3)
+        assert isinf(float('inf'))
+        assert not isnan(3.5)
+        assert not isinf(3.5)
+        assert not isnan(float('inf'))
+        assert not isinf(float('nan'))
+        assert (isnan(array([0.2, float('inf'), float('nan')])) == [False, False, True]).all()
+        assert (isinf(array([0.2, float('inf'), float('nan')])) == [False, True, False]).all()
+        assert isinf(array([0.2])).dtype.kind == 'b'
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -12,7 +12,7 @@
 from pypy.module.micronumpy.compile import (FakeSpace,
     IntObject, Parser, InterpreterState)
 from pypy.module.micronumpy.interp_numarray import (W_NDimArray,
-     BaseArray)
+     BaseArray, W_FlatIterator)
 from pypy.rlib.nonconst import NonConstant
 
 
@@ -287,6 +287,27 @@
                                 'jump': 1,
                                 'arraylen_gc': 1})
 
+    def define_take():
+        return """
+        a = |10|
+        b = take(a, [1, 1, 3, 2])
+        b -> 2
+        """
+
+    def test_take(self):
+        result = self.run("take")
+        assert result == 3
+        self.check_simple_loop({'getinteriorfield_raw': 2,
+                                'cast_float_to_int': 1,
+                                'int_lt': 1,
+                                'int_ge': 2,
+                                'guard_false': 3,
+                                'setinteriorfield_raw': 1,
+                                'int_mul': 1,
+                                'int_add': 3,
+                                'jump': 1,
+                                'arraylen_gc': 2})
+
     def define_multidim():
         return """
         a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
@@ -369,7 +390,71 @@
                                 'setinteriorfield_raw': 1, 'int_add': 2,
                                 'int_ge': 1, 'guard_false': 1, 'jump': 1,
                                 'arraylen_gc': 1})
+    def define_flat_iter():
+        return '''
+        a = |30|
+        b = flat(a)
+        c = b + a
+        c -> 3
+        '''
 
+    def test_flat_iter(self):
+        result = self.run("flat_iter")
+        assert result == 6
+        self.check_trace_count(1)
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
+                                'int_ge': 1, 'guard_false': 1,
+                                'arraylen_gc': 1, 'jump': 1})
+
+    def define_flat_getitem():
+        return '''
+        a = |30|
+        b = flat(a)
+        b -> 4: -> 6
+        '''
+
+    def test_flat_getitem(self):
+        result = self.run("flat_getitem")
+        assert result == 10.0
+        self.check_trace_count(1)
+        self.check_simple_loop({'getinteriorfield_raw': 1,
+                                'setinteriorfield_raw': 1,
+                                'int_lt': 1,
+                                'int_ge': 1,
+                                'int_add': 3,
+                                'guard_true': 1,
+                                'guard_false': 1,
+                                'arraylen_gc': 2,
+                                'jump': 1})
+
+    def define_flat_setitem():
+        return '''
+        a = |30|
+        b = flat(a)
+        b[4:] = a->:26
+        a -> 5
+        '''
+
+    def test_flat_setitem(self):
+        result = self.run("flat_setitem")
+        assert result == 1.0
+        self.check_trace_count(1)
+        # XXX not ideal, but hey, let's ignore it for now
+        self.check_simple_loop({'getinteriorfield_raw': 1,
+                                'setinteriorfield_raw': 1,
+                                'int_lt': 1,
+                                'int_gt': 1,
+                                'int_add': 4,
+                                'guard_true': 2,
+                                'arraylen_gc': 2,
+                                'jump': 1,
+                                'int_sub': 1,
+                                # XXX bad part
+                                'int_and': 1,
+                                'int_mod': 1,
+                                'int_rshift': 1,
+                                })
 
 class TestNumpyOld(LLJitMixin):
     def setup_class(cls):
diff --git a/pypy/module/micronumpy/tool/numready/main.py b/pypy/module/micronumpy/tool/numready/main.py
--- a/pypy/module/micronumpy/tool/numready/main.py
+++ b/pypy/module/micronumpy/tool/numready/main.py
@@ -73,9 +73,8 @@
     for line in lines:
         kind, name = line.split(" : ", 1)
         subitems = None
-        if kind == KINDS["TYPE"]:
-            if name in ['ndarray', 'dtype']:
-                subitems = find_numpy_items(python, modname, name)
+        if kind == KINDS["TYPE"] and name in SPECIAL_NAMES and attr is None:
+            subitems = find_numpy_items(python, modname, name)
         items.add(Item(name, kind, subitems))
     return items
 
@@ -89,15 +88,20 @@
                 l[i].append(lst[k * lgt + i])
     return l
 
+SPECIAL_NAMES = ["ndarray", "dtype", "generic"]
+
 def main(argv):
     cpy_items = find_numpy_items("/usr/bin/python")
     pypy_items = find_numpy_items(argv[1], "numpypy")
     all_items = []
 
-    msg = '%d/%d names, %d/%d ndarray attributes, %d/%d dtype attributes' % (
-        len(pypy_items), len(cpy_items), len(pypy_items['ndarray'].subitems),
-        len(cpy_items['ndarray'].subitems), len(pypy_items['dtype'].subitems),
-        len(cpy_items['dtype'].subitems))
+    msg = "{:d}/{:d} names".format(len(pypy_items), len(cpy_items)) + " "
+    msg += ", ".join(
+        "{:d}/{:d} {} attributes".format(
+            len(pypy_items[name].subitems), len(cpy_items[name].subitems), name
+        )
+        for name in SPECIAL_NAMES
+    )
     for item in cpy_items:
         pypy_exists = item in pypy_items
         if item.subitems:
@@ -114,6 +118,6 @@
         with open(argv[2], 'w') as f:
             f.write(html.encode("utf-8"))
     else:
-        with tempfile.NamedTemporaryFile(delete=False) as f:
+        with tempfile.NamedTemporaryFile(delete=False, suffix=".html") as f:
             f.write(html.encode("utf-8"))
         print "Saved in: %s" % f.name
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -23,6 +23,16 @@
         )
     return dispatcher
 
+def raw_unary_op(func):
+    specialize.argtype(1)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v):
+        return func(
+            self,
+            self.for_computation(self.unbox(v))
+        )
+    return dispatcher
+
 def simple_binary_op(func):
     specialize.argtype(1, 2)(func)
     @functools.wraps(func)
@@ -95,7 +105,9 @@
         ))
 
     def read_bool(self, storage, width, i, offset):
-        raise NotImplementedError
+        return bool(self.for_computation(
+            libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+                                 width, storage, i, offset)))
 
     def store(self, storage, width, i, offset, box):
         value = self.unbox(box)
@@ -137,6 +149,14 @@
     def abs(self, v):
         return abs(v)
 
+    @raw_unary_op
+    def isnan(self, v):
+        return False
+
+    @raw_unary_op
+    def isinf(self, v):
+        return False
+
     @raw_binary_op
     def eq(self, v1, v2):
         return v1 == v2
@@ -171,7 +191,7 @@
     @simple_binary_op
     def min(self, v1, v2):
         return min(v1, v2)
-    
+
 
 class Bool(BaseType, Primitive):
     T = lltype.Bool
@@ -189,11 +209,6 @@
         else:
             return self.False
 
-
-    def read_bool(self, storage, width, i, offset):
-        return libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
-                                    width, storage, i, offset)
-
     def coerce_subtype(self, space, w_subtype, w_item):
         # Doesn't return subclasses so it can return the constants.
         return self._coerce(space, w_item)
@@ -214,6 +229,18 @@
     def default_fromstring(self, space):
         return self.box(False)
 
+    @simple_binary_op
+    def bitwise_and(self, v1, v2):
+        return v1 & v2
+
+    @simple_binary_op
+    def bitwise_or(self, v1, v2):
+        return v1 | v2
+
+    @simple_unary_op
+    def invert(self, v):
+        return ~v
+
 class Integer(Primitive):
     _mixin_ = True
 
@@ -270,6 +297,10 @@
     def bitwise_or(self, v1, v2):
         return v1 | v2
 
+    @simple_unary_op
+    def invert(self, v):
+        return ~v
+
 class Int8(BaseType, Integer):
     T = rffi.SIGNEDCHAR
     BoxType = interp_boxes.W_Int8Box
@@ -448,6 +479,14 @@
         except ValueError:
             return rfloat.NAN
 
+    @raw_unary_op
+    def isnan(self, v):
+        return rfloat.isnan(v)
+
+    @raw_unary_op
+    def isinf(self, v):
+        return rfloat.isinf(v)
+
 
 class Float32(BaseType, Float):
     T = rffi.FLOAT
diff --git a/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
--- a/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
+++ b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
@@ -98,15 +98,15 @@
         from numpypy import array, var
         a = array([[1,2],[3,4]])
         assert var(a) == 1.25
-        #assert (var(a,0) == array([ 1.,  1.])).all()
-        #assert (var(a,1) == array([ 0.25,  0.25])).all()
+        assert (var(a,0) == array([ 1.,  1.])).all()
+        assert (var(a,1) == array([ 0.25,  0.25])).all()
 
     def test_std(self):
         from numpypy import array, std
         a = array([[1, 2], [3, 4]])
         assert std(a) ==  1.1180339887498949
-        #assert (std(a, axis=0) == array([ 1.,  1.])).all()
-        #assert (std(a, axis=1) == array([ 0.5,  0.5])).all()
+        assert (std(a, axis=0) == array([ 1.,  1.])).all()
+        assert (std(a, axis=1) == array([ 0.5,  0.5])).all()
 
     def test_mean(self):
         from numpypy import array, mean, arange
@@ -136,4 +136,4 @@
         raises(NotImplementedError, "transpose(x, axes=(1, 0, 2))")
         # x = ones((1, 2, 3))
         # assert transpose(x, (1, 0, 2)).shape == (2, 1, 3)
-
+        
diff --git a/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py b/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py
@@ -0,0 +1,144 @@
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestBaseRepr(BaseNumpyAppTest):
+    def test_base3(self):
+        from numpypy import base_repr
+        assert base_repr(3**5, 3) == '100000'
+
+    def test_positive(self):
+        from numpypy import base_repr
+        assert base_repr(12, 10) == '12'
+        assert base_repr(12, 10, 4) == '000012'
+        assert base_repr(12, 4) == '30'
+        assert base_repr(3731624803700888, 36) == '10QR0ROFCEW'
+
+    def test_negative(self):
+        from numpypy import base_repr
+        assert base_repr(-12, 10) == '-12'
+        assert base_repr(-12, 10, 4) == '-000012'
+        assert base_repr(-12, 4) == '-30'
+
+class AppTestRepr(BaseNumpyAppTest):
+    def test_repr(self):
+        from numpypy import array
+        assert repr(array([1, 2, 3, 4])) == 'array([1, 2, 3, 4])'
+
+    def test_repr_2(self):
+        from numpypy import array, zeros
+        int_size = array(5).dtype.itemsize
+        a = array(range(5), float)
+        assert repr(a) == "array([ 0.,  1.,  2.,  3.,  4.])"
+        a = array([], float)
+        assert repr(a) == "array([], dtype=float64)"
+        a = zeros(1001)
+        assert repr(a) == "array([ 0.,  0.,  0., ...,  0.,  0.,  0.])"
+        a = array(range(5), long)
+        if a.dtype.itemsize == int_size:
+            assert repr(a) == "array([0, 1, 2, 3, 4])"
+        else:
+            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int64)"
+        a = array(range(5), 'int32')
+        if a.dtype.itemsize == int_size:
+            assert repr(a) == "array([0, 1, 2, 3, 4])"
+        else:
+            assert repr(a) == "array([0, 1, 2, 3, 4], dtype=int32)"
+        a = array([], long)
+        assert repr(a) == "array([], dtype=int64)"
+        a = array([True, False, True, False], "?")
+        assert repr(a) == "array([ True, False,  True, False], dtype=bool)"
+        a = zeros([])
+        assert repr(a) == "array(0.0)"
+        a = array(0.2)
+        assert repr(a) == "array(0.2)"
+        a = array([2])
+        assert repr(a) == "array([2])"
+
+    def test_repr_multi(self):
+        from numpypy import arange, zeros, array
+        a = zeros((3, 4))
+        assert repr(a) == '''array([[ 0.,  0.,  0.,  0.],
+       [ 0.,  0.,  0.,  0.],
+       [ 0.,  0.,  0.,  0.]])'''
+        a = zeros((2, 3, 4))
+        assert repr(a) == '''array([[[ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.]],
+
+       [[ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.],
+        [ 0.,  0.,  0.,  0.]]])'''
+        a = arange(1002).reshape((2, 501))
+        assert repr(a) == '''array([[   0,    1,    2, ...,  498,  499,  500],
+       [ 501,  502,  503, ...,  999, 1000, 1001]])'''
+        assert repr(a.T) == '''array([[   0,  501],
+       [   1,  502],
+       [   2,  503],
+       ..., 
+       [ 498,  999],
+       [ 499, 1000],
+       [ 500, 1001]])'''
+        a = arange(2).reshape((2,1))
+        assert repr(a) == '''array([[0],
+       [1]])'''
+
+    def test_repr_slice(self):
+        from numpypy import array, zeros
+        a = array(range(5), float)
+        b = a[1::2]
+        assert repr(b) == "array([ 1.,  3.])"
+        a = zeros(2002)
+        b = a[::2]
+        assert repr(b) == "array([ 0.,  0.,  0., ...,  0.,  0.,  0.])"
+        a = array((range(5), range(5, 10)), dtype="int16")
+        b = a[1, 2:]
+        assert repr(b) == "array([7, 8, 9], dtype=int16)"
+        # an empty slice prints its shape
+        b = a[2:1, ]
+        assert repr(b) == "array([], shape=(0, 5), dtype=int16)"
+
+    def test_str(self):
+        from numpypy import array, zeros
+        a = array(range(5), float)
+        assert str(a) == "[ 0.  1.  2.  3.  4.]"
+        assert str((2 * a)[:]) == "[ 0.  2.  4.  6.  8.]"
+        a = zeros(1001)
+        assert str(a) == "[ 0.  0.  0. ...,  0.  0.  0.]"
+
+        a = array(range(5), dtype=long)
+        assert str(a) == "[0 1 2 3 4]"
+        a = array([True, False, True, False], dtype="?")
+        assert str(a) == "[ True False  True False]"
+
+        a = array(range(5), dtype="int8")
+        assert str(a) == "[0 1 2 3 4]"
+
+        a = array(range(5), dtype="int16")
+        assert str(a) == "[0 1 2 3 4]"
+
+        a = array((range(5), range(5, 10)), dtype="int16")
+        assert str(a) == "[[0 1 2 3 4]\n [5 6 7 8 9]]"
+
+        a = array(3, dtype=int)
+        assert str(a) == "3"
+
+        a = zeros((400, 400), dtype=int)
+        assert str(a) == '[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n ..., \n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]'
+        a = zeros((2, 2, 2))
+        r = str(a)
+        assert r == '[[[ 0.  0.]\n  [ 0.  0.]]\n\n [[ 0.  0.]\n  [ 0.  0.]]]'
+
+    def test_str_slice(self):
+        from numpypy import array, zeros
+        a = array(range(5), float)
+        b = a[1::2]
+        assert str(b) == "[ 1.  3.]"
+        a = zeros(2002)
+        b = a[::2]
+        assert str(b) == "[ 0.  0.  0. ...,  0.  0.  0.]"
+        a = array((range(5), range(5, 10)), dtype="int16")
+        b = a[1, 2:]
+        assert str(b) == "[7 8 9]"
+        b = a[2:1, ]
+        assert str(b) == "[]"
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -150,6 +150,8 @@
                 self._see_getsetproperty(x)
         if isinstance(x, r_singlefloat):
             self._wrap_not_rpython(x)
+        if isinstance(x, list):
+            self._wrap_not_rpython(x)
         return w_some_obj()
     wrap._annspecialcase_ = "specialize:argtype(1)"
 
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -130,19 +130,29 @@
         if self is other:
             return 0
         else:
-            raise TypeError("Symbolics can not be compared!")
+            raise TypeError("Symbolics cannot be compared! (%r, %r)"
+                            % (self, other))
 
     def __hash__(self):
-        raise TypeError("Symbolics are not hashable!")
+        raise TypeError("Symbolics are not hashable! %r" % (self,))
 
     def __nonzero__(self):
-        raise TypeError("Symbolics are not comparable")
+        raise TypeError("Symbolics are not comparable! %r" % (self,))
 
 class ComputedIntSymbolic(Symbolic):
 
     def __init__(self, compute_fn):
         self.compute_fn = compute_fn
 
+    def __repr__(self):
+        # repr(self.compute_fn) can arrive back here in an
+        # infinite recursion
+        try:
+            name = self.compute_fn.__name__
+        except (AttributeError, TypeError):
+            name = hex(id(self.compute_fn))
+        return '%s(%r)' % (self.__class__.__name__, name)
+
     def annotation(self):
         from pypy.annotation import model
         return model.SomeInteger()
@@ -157,6 +167,9 @@
         self.expr = expr
         self.default = default
 
+    def __repr__(self):
+        return '%s(%r)' % (self.__class__.__name__, self.expr)
+
     def annotation(self):
         from pypy.annotation import model
         return model.SomeInteger()
diff --git a/pypy/rlib/rstacklet.py b/pypy/rlib/rstacklet.py
--- a/pypy/rlib/rstacklet.py
+++ b/pypy/rlib/rstacklet.py
@@ -1,3 +1,4 @@
+import sys
 from pypy.rlib import _rffi_stacklet as _c
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import we_are_translated
@@ -72,6 +73,11 @@
     if translated:
         assert config is not None, ("you have to pass a valid config, "
                                     "e.g. from 'driver.config'")
+    elif '__pypy__' in sys.builtin_module_names:
+        import py
+        py.test.skip("cannot run the stacklet tests on top of pypy: "
+                     "calling directly the C function stacklet_switch() "
+                     "will crash, depending on details of your config")
     if config is not None:
         assert config.translation.continuation, (
             "stacklet: you have to translate with --continuation")
diff --git a/pypy/rpython/lltypesystem/llgroup.py b/pypy/rpython/lltypesystem/llgroup.py
--- a/pypy/rpython/lltypesystem/llgroup.py
+++ b/pypy/rpython/lltypesystem/llgroup.py
@@ -76,6 +76,10 @@
         self.index = memberindex
         self.member = grp.members[memberindex]._as_ptr()
 
+    def __repr__(self):
+        return '%s(%s, %s)' % (self.__class__.__name__,
+                               self.grpptr, self.index)
+
     def __nonzero__(self):
         return True
 
diff --git a/pypy/rpython/lltypesystem/llmemory.py b/pypy/rpython/lltypesystem/llmemory.py
--- a/pypy/rpython/lltypesystem/llmemory.py
+++ b/pypy/rpython/lltypesystem/llmemory.py
@@ -32,7 +32,8 @@
             self.known_nonneg()):
             return True
         else:
-            raise TypeError("Symbolics can not be compared!")
+            raise TypeError("Symbolics cannot be compared! (%r, %r)"
+                            % (self, other))
 
     def __lt__(self, other):
         return not self.__ge__(other)
diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -323,6 +323,17 @@
         hop.exception_is_here()
         return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
 
+    def rtype_method_pop(self, hop):
+        if hop.nb_args == 2:
+            v_args = hop.inputargs(self, self.key_repr)
+            target = ll_pop
+        elif hop.nb_args == 3:
+            v_args = hop.inputargs(self, self.key_repr, self.value_repr)
+            target = ll_pop_default
+        hop.exception_is_here()
+        v_res = hop.gendirectcall(target, *v_args)
+        return self.recast_value(hop.llops, v_res)
+
 class __extend__(pairtype(DictRepr, rmodel.Repr)):
 
     def rtype_getitem((r_dict, r_key), hop):
@@ -874,3 +885,18 @@
     r.item1 = recast(ELEM.TO.item1, entry.value)
     _ll_dict_del(dic, i)
     return r
+
+def ll_pop(dic, key):
+    i = ll_dict_lookup(dic, key, dic.keyhash(key))
+    if not i & HIGHEST_BIT:
+        value = ll_get_value(dic, i)
+        _ll_dict_del(dic, i)
+        return value
+    else:
+        raise KeyError
+
+def ll_pop_default(dic, key, dfl):
+    try:
+        return ll_pop(dic, key)
+    except KeyError:
+        return dfl
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -27,6 +27,10 @@
         self.c_name = c_name
         self.TP = TP
 
+    def __repr__(self):
+        return '%s(%r, %s)' % (self.__class__.__name__,
+                               self.c_name, self.TP)
+
     def annotation(self):
         return lltype_to_annotation(self.TP)
 
diff --git a/pypy/rpython/ootypesystem/rdict.py b/pypy/rpython/ootypesystem/rdict.py
--- a/pypy/rpython/ootypesystem/rdict.py
+++ b/pypy/rpython/ootypesystem/rdict.py
@@ -160,6 +160,16 @@
         hop.exception_is_here()
         return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
 
+    def rtype_method_pop(self, hop):
+        if hop.nb_args == 2:
+            v_args = hop.inputargs(self, self.key_repr)
+            target = ll_pop
+        elif hop.nb_args == 3:
+            v_args = hop.inputargs(self, self.key_repr, self.value_repr)
+            target = ll_pop_default
+        hop.exception_is_here()
+        return hop.gendirectcall(target, *v_args)
+
     def __get_func(self, interp, r_func, fn, TYPE):
         if isinstance(r_func, MethodOfFrozenPBCRepr):
             obj = r_func.r_im_self.convert_const(fn.im_self)
@@ -370,6 +380,20 @@
         return res
     raise KeyError
 
+def ll_pop(d, key):
+    if d.ll_contains(key):
+        value = d.ll_get(key)
+        d.ll_remove(key)
+        return value
+    else:
+        raise KeyError
+
+def ll_pop_default(d, key, dfl):
+    try:
+        return ll_pop(d, key)
+    except KeyError:
+        return dfl
+
 # ____________________________________________________________
 #
 #  Iteration.
diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -25,37 +25,37 @@
 class BaseTestRdict(BaseRtypingTest):
 
     def test_dict_creation(self):
-        def createdict(i): 
+        def createdict(i):
             d = {'hello' : i}
             return d['hello']
 
         res = self.interpret(createdict, [42])
         assert res == 42
 
-    def test_dict_getitem_setitem(self): 
-        def func(i): 
+    def test_dict_getitem_setitem(self):
+        def func(i):
             d = {'hello' : i}
             d['world'] = i + 1
-            return d['hello'] * d['world'] 
+            return d['hello'] * d['world']
         res = self.interpret(func, [6])
         assert res == 42
 
-    def test_dict_getitem_keyerror(self): 
-        def func(i): 
+    def test_dict_getitem_keyerror(self):
+        def func(i):
             d = {'hello' : i}
             try:
                 return d['world']
             except KeyError:
-                return 0 
+                return 0
         res = self.interpret(func, [6])
         assert res == 0
 
     def test_dict_del_simple(self):
-        def func(i): 
+        def func(i):
             d = {'hello' : i}
             d['world'] = i + 1
             del d['hello']
-            return len(d) 
+            return len(d)
         res = self.interpret(func, [6])
         assert res == 1
 
@@ -71,7 +71,7 @@
         assert res == True
 
     def test_empty_strings(self):
-        def func(i): 
+        def func(i):
             d = {'' : i}
             del d['']
             try:
@@ -83,7 +83,7 @@
         res = self.interpret(func, [6])
         assert res == 1
 
-        def func(i): 
+        def func(i):
             d = {'' : i}
             del d['']
             d[''] = i + 1
@@ -146,8 +146,8 @@
             d1 = {}
             d1['hello'] = i + 1
             d2 = {}
-            d2['world'] = d1 
-            return d2['world']['hello'] 
+            d2['world'] = d1
+            return d2['world']['hello']
         res = self.interpret(func, [5])
         assert res == 6
 
@@ -297,7 +297,7 @@
             a = 0
             for k, v in items:
                 b += isinstance(k, B)
-                a += isinstance(v, A) 
+                a += isinstance(v, A)
             return 3*b+a
         res = self.interpret(func, [])
         assert res == 8
@@ -316,7 +316,7 @@
             a = 0
             for k, v in dic.iteritems():
                 b += isinstance(k, B)
-                a += isinstance(v, A) 
+                a += isinstance(v, A)
             return 3*b+a
         res = self.interpret(func, [])
         assert res == 8
@@ -342,11 +342,11 @@
     def test_dict_contains_with_constant_dict(self):
         dic = {'4':1000, ' 8':200}
         def func(i):
-            return chr(i) in dic 
-        res = self.interpret(func, [ord('4')]) 
+            return chr(i) in dic
+        res = self.interpret(func, [ord('4')])
         assert res is True
-        res = self.interpret(func, [1]) 
-        assert res is False 
+        res = self.interpret(func, [1])
+        assert res is False
 
     def test_dict_or_none(self):
         class A:
@@ -413,7 +413,7 @@
             return g(get)
 
         res = self.interpret(f, [])
-        assert res == 2    
+        assert res == 2
 
     def test_specific_obscure_bug(self):
         class A: pass
@@ -622,6 +622,42 @@
         res = self.interpret(func, [])
         assert res in [5263, 6352]
 
+    def test_dict_pop(self):
+        def f(n, default):
+            d = {}
+            d[2] = 3
+            d[4] = 5
+            if default == -1:
+                try:
+                    x = d.pop(n)
+                except KeyError:
+                    x = -1
+            else:
+                x = d.pop(n, default)
+            return x * 10 + len(d)
+        res = self.interpret(f, [2, -1])
+        assert res == 31
+        res = self.interpret(f, [3, -1])
+        assert res == -8
+        res = self.interpret(f, [2, 5])
+        assert res == 31
+
+    def test_dict_pop_instance(self):
+        class A(object):
+            pass
+        def f(n):
+            d = {}
+            d[2] = A()
+            x = d.pop(n, None)
+            if x is None:
+                return 12
+            else:
+                return 15
+        res = self.interpret(f, [2])
+        assert res == 15
+        res = self.interpret(f, [700])
+        assert res == 12
+
 class TestLLtype(BaseTestRdict, LLRtypeMixin):
     def test_dict_but_not_with_char_keys(self):
         def func(i):
@@ -633,19 +669,19 @@
         res = self.interpret(func, [6])
         assert res == 0
 
-    def test_deleted_entry_reusage_with_colliding_hashes(self): 
-        def lowlevelhash(value): 
+    def test_deleted_entry_reusage_with_colliding_hashes(self):
+        def lowlevelhash(value):
             p = rstr.mallocstr(len(value))
             for i in range(len(value)):
                 p.chars[i] = value[i]
-            return rstr.LLHelpers.ll_strhash(p) 
+            return rstr.LLHelpers.ll_strhash(p)
 
-        def func(c1, c2): 
-            c1 = chr(c1) 
-            c2 = chr(c2) 
+        def func(c1, c2):
+            c1 = chr(c1)
+            c2 = chr(c2)
             d = {}
             d[c1] = 1
-            d[c2] = 2 
+            d[c2] = 2
             del d[c1]
             return d[c2]
 
@@ -653,7 +689,7 @@
         base = rdict.DICT_INITSIZE
         for y in range(0, 256):
             y = chr(y)
-            y_hash = lowlevelhash(y) % base 
+            y_hash = lowlevelhash(y) % base
             char_by_hash.setdefault(y_hash, []).append(y)
 
         x, y = char_by_hash[0][:2]   # find a collision
@@ -661,18 +697,18 @@
         res = self.interpret(func, [ord(x), ord(y)])
         assert res == 2
 
-        def func2(c1, c2): 
-            c1 = chr(c1) 
-            c2 = chr(c2) 
+        def func2(c1, c2):
+            c1 = chr(c1)
+            c2 = chr(c2)
             d = {}
             d[c1] = 1
-            d[c2] = 2 
+            d[c2] = 2
             del d[c1]
             d[c1] = 3
-            return d 
+            return d
 
         res = self.interpret(func2, [ord(x), ord(y)])
-        for i in range(len(res.entries)): 
+        for i in range(len(res.entries)):
             assert not (res.entries.everused(i) and not res.entries.valid(i))
 
         def func3(c0, c1, c2, c3, c4, c5, c6, c7):
@@ -687,9 +723,9 @@
             c7 = chr(c7) ; d[c7] = 1; del d[c7]
             return d
 
-        if rdict.DICT_INITSIZE != 8: 
+        if rdict.DICT_INITSIZE != 8:
             py.test.skip("make dict tests more indepdent from initsize")
-        res = self.interpret(func3, [ord(char_by_hash[i][0]) 
+        res = self.interpret(func3, [ord(char_by_hash[i][0])
                                    for i in range(rdict.DICT_INITSIZE)])
         count_frees = 0
         for i in range(len(res.entries)):
@@ -707,9 +743,9 @@
                     del d[chr(ord('a') + i)]
             return d
         res = self.interpret(func, [0])
-        assert len(res.entries) > rdict.DICT_INITSIZE 
+        assert len(res.entries) > rdict.DICT_INITSIZE
         res = self.interpret(func, [1])
-        assert len(res.entries) == rdict.DICT_INITSIZE 
+        assert len(res.entries) == rdict.DICT_INITSIZE
 
     def test_dict_valid_resize(self):
         # see if we find our keys after resize
@@ -844,7 +880,7 @@
 
     def test_prebuilt_list_of_addresses(self):
         from pypy.rpython.lltypesystem import llmemory
-        
+
         TP = lltype.Struct('x', ('y', lltype.Signed))
         a = lltype.malloc(TP, flavor='raw', immortal=True)
         b = lltype.malloc(TP, flavor='raw', immortal=True)
@@ -858,7 +894,7 @@
 
         d = {a_a: 3, a_b: 4, a_c: 5}
         d[a0] = 8
-        
+
         def func(i):
             if i == 0:
                 ptr = a
@@ -888,7 +924,7 @@
             return a == b
         def rhash(a):
             return 3
-        
+
         def func(i):
             d = r_dict(eq, rhash, force_non_null=True)
             if not i:
diff --git a/pypy/translator/goal/targetnopstandalone.py b/pypy/translator/goal/targetnopstandalone.py
--- a/pypy/translator/goal/targetnopstandalone.py
+++ b/pypy/translator/goal/targetnopstandalone.py
@@ -7,10 +7,8 @@
 actually implementing argv of the executable.
 """
 
-import os, sys
-
-def debug(msg): 
-    os.write(2, "debug: " + msg + '\n')
+def debug(msg):
+    print "debug:", msg
 
 # __________  Entry point  __________
 


More information about the pypy-commit mailing list