summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes4
-rw-r--r--.mailmap1
-rw-r--r--.travis.yml4
-rw-r--r--LICENSE.txt2
-rw-r--r--benchmarks/benchmarks/bench_core.py37
-rw-r--r--benchmarks/benchmarks/bench_random.py2
-rw-r--r--doc/release/1.12.0-notes.rst1227
-rw-r--r--doc/release/1.12.1-notes.rst9
-rw-r--r--doc/release/1.13.0-notes.rst122
-rw-r--r--doc/source/reference/arrays.indexing.rst4
-rw-r--r--doc/source/reference/arrays.ndarray.rst8
-rw-r--r--doc/source/reference/arrays.scalars.rst15
-rw-r--r--doc/source/reference/c-api.array.rst8
-rw-r--r--doc/source/reference/c-api.iterator.rst29
-rw-r--r--doc/source/reference/maskedarray.baseclass.rst2
-rw-r--r--doc/source/user/quickstart.rst27
-rw-r--r--numpy/add_newdocs.py11
-rw-r--r--numpy/core/_methods.py4
-rw-r--r--numpy/core/code_generators/cversions.txt3
-rw-r--r--numpy/core/code_generators/numpy_api.py2
-rw-r--r--numpy/core/fromnumeric.py16
-rw-r--r--numpy/core/getlimits.py289
-rw-r--r--numpy/core/include/numpy/ndarraytypes.h8
-rw-r--r--numpy/core/memmap.py4
-rw-r--r--numpy/core/numeric.py11
-rw-r--r--numpy/core/records.py36
-rw-r--r--numpy/core/setup.py5
-rw-r--r--numpy/core/setup_common.py5
-rw-r--r--numpy/core/src/multiarray/cblasfuncs.c131
-rw-r--r--numpy/core/src/multiarray/compiled_base.c84
-rw-r--r--numpy/core/src/multiarray/descriptor.c57
-rw-r--r--numpy/core/src/multiarray/mapping.c88
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c97
-rw-r--r--numpy/core/src/multiarray/nditer_constr.c101
-rw-r--r--numpy/core/src/multiarray/nditer_impl.h2
-rw-r--r--numpy/core/src/multiarray/nditer_pywrap.c14
-rw-r--r--numpy/core/src/multiarray/sequence.c90
-rw-r--r--numpy/core/src/private/lowlevel_strided_loops.h125
-rw-r--r--numpy/core/src/umath/loops.c.src2
-rw-r--r--numpy/core/src/umath/reduction.c46
-rw-r--r--numpy/core/src/umath/ufunc_object.c183
-rw-r--r--numpy/core/tests/test_arrayprint.py1
-rw-r--r--numpy/core/tests/test_datetime.py6
-rw-r--r--numpy/core/tests/test_dtype.py7
-rw-r--r--numpy/core/tests/test_getlimits.py41
-rw-r--r--numpy/core/tests/test_mem_overlap.py466
-rw-r--r--numpy/core/tests/test_memmap.py6
-rw-r--r--numpy/core/tests/test_multiarray.py55
-rw-r--r--numpy/core/tests/test_nditer.py100
-rw-r--r--numpy/core/tests/test_records.py26
-rw-r--r--numpy/core/tests/test_umath.py37
-rw-r--r--numpy/core/tests/test_unicode.py12
-rw-r--r--numpy/distutils/conv_template.py2
-rw-r--r--numpy/distutils/from_template.py2
-rw-r--r--numpy/distutils/mingw32ccompiler.py116
-rw-r--r--numpy/distutils/system_info.py2
-rw-r--r--numpy/distutils/tests/test_misc_util.py1
-rw-r--r--numpy/doc/indexing.py4
-rwxr-xr-xnumpy/f2py/crackfortran.py3
-rw-r--r--numpy/f2py/tests/src/parameter/constant_compound.f9015
-rw-r--r--numpy/f2py/tests/src/parameter/constant_non_compound.f9023
-rw-r--r--numpy/f2py/tests/test_parameter.py20
-rw-r--r--numpy/fft/fftpack.py4
-rw-r--r--numpy/fft/tests/test_fftpack.py28
-rw-r--r--numpy/fft/tests/test_helper.py1
-rw-r--r--numpy/lib/function_base.py32
-rw-r--r--numpy/lib/index_tricks.py26
-rw-r--r--numpy/lib/npyio.py50
-rw-r--r--numpy/lib/shape_base.py134
-rw-r--r--numpy/lib/stride_tricks.py2
-rw-r--r--numpy/lib/tests/test_function_base.py10
-rw-r--r--numpy/lib/tests/test_nanfunctions.py12
-rw-r--r--numpy/lib/tests/test_packbits.py188
-rw-r--r--numpy/lib/tests/test_shape_base.py119
-rw-r--r--numpy/lib/tests/test_stride_tricks.py2
-rw-r--r--numpy/lib/tests/test_type_check.py9
-rw-r--r--numpy/lib/type_check.py8
-rw-r--r--numpy/lib/user_array.py6
-rw-r--r--numpy/ma/core.py71
-rw-r--r--numpy/ma/extras.py23
-rw-r--r--numpy/ma/tests/test_core.py38
-rw-r--r--numpy/ma/tests/test_extras.py27
-rw-r--r--numpy/polynomial/chebyshev.py4
-rw-r--r--numpy/polynomial/hermite.py2
-rw-r--r--numpy/polynomial/hermite_e.py2
-rw-r--r--numpy/polynomial/laguerre.py2
-rw-r--r--numpy/polynomial/legendre.py2
-rw-r--r--numpy/polynomial/polynomial.py2
-rw-r--r--numpy/random/mtrand/mtrand.pyx33
-rw-r--r--numpy/random/tests/test_random.py44
-rw-r--r--numpy/testing/nosetester.py2
-rw-r--r--numpy/testing/tests/test_utils.py209
-rw-r--r--numpy/testing/utils.py59
-rw-r--r--pavement.py21
-rwxr-xr-xtools/announce.py9
-rwxr-xr-xtools/travis-test.sh22
96 files changed, 3730 insertions, 1333 deletions
diff --git a/.gitattributes b/.gitattributes
index 82162cb8d..6e1de1b3d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,9 @@
+# Line endings for Windows scripts
* text=auto
tools/win32build/nsis_scripts/*.nsi.in eol=crlf
# Numerical data files
numpy/lib/tests/data/*.npy binary
+
+# Release notes, reduce number of conflicts.
+doc/release/*.rst merge=union
diff --git a/.mailmap b/.mailmap
index e2a9adbaa..02b9db533 100644
--- a/.mailmap
+++ b/.mailmap
@@ -66,6 +66,7 @@ Evgeni Burovski <evgeny.burovskiy@gmail.com> Evgeni Burovski <evgeni@burovski.me
Evgeny Toder <evgeny.toder@jpmorgan.com> eltjpm <evgeny.toder@jpmorgan.com>
Fernando Perez <Fernando.Perez@berkeley.edu> Fernando Perez <fperez@fperez.org>
Friedrich Dunne <dunneff@tcd.ie> dunneff <dunneff@tcd.ie>
+Frederic Bastien <nouiz@nouiz.org> Frederic <nouiz@nouiz.org>
Gael Varoquaux <gael.varoquaux@normalesup.org> GaelVaroquaux <gael.varoquaux@normalesup.org>
Gerrit Holl <gerrit.holl@utoronto.ca> Gerrit Holl <g.holl@reading.ac.uk>
Giuseppe Venturini <ggventurini@users.noreply.github.com> ggventurini <ggventurini@users.noreply.github.com>
diff --git a/.travis.yml b/.travis.yml
index cde8db23d..787d00c9a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,13 +34,13 @@ python:
- 2.7
- 3.4
- 3.5
- - 3.6-dev
+ - 3.6
matrix:
include:
- python: 2.7
env: PY3_COMPATIBILITY_CHECK=1
- python: 2.7
- env: USE_CHROOT=1 ARCH=i386 DIST=trusty PYTHON=2.7
+ env: USE_CHROOT=1 ARCH=i386 DIST=yakkety PYTHON=2.7
sudo: true
dist: trusty
addons:
diff --git a/LICENSE.txt b/LICENSE.txt
index 9014534ab..906c7b536 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2005-2016, NumPy Developers.
+Copyright (c) 2005-2017, NumPy Developers.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/benchmarks/benchmarks/bench_core.py b/benchmarks/benchmarks/bench_core.py
index 6701917cc..1f7c23310 100644
--- a/benchmarks/benchmarks/bench_core.py
+++ b/benchmarks/benchmarks/bench_core.py
@@ -130,3 +130,40 @@ class CountNonzero(Benchmark):
if self.x.ndim >= 2:
np.count_nonzero(self.x, axis=(
self.x.ndim - 1, self.x.ndim - 2))
+
+
+class PackBits(Benchmark):
+ param_names = ['dtype']
+ params = [[np.bool, np.uintp]]
+ def setup(self, dtype):
+ self.d = np.ones(10000, dtype=dtype)
+ self.d2 = np.ones((200, 1000), dtype=dtype)
+
+ def time_packbits(self, dtype):
+ np.packbits(self.d)
+
+ def time_packbits_axis0(self, dtype):
+ np.packbits(self.d2, axis=0)
+
+ def time_packbits_axis1(self, dtype):
+ np.packbits(self.d2, axis=1)
+
+
+class UnpackBits(Benchmark):
+ def setup(self):
+ self.d = np.ones(10000, dtype=np.uint8)
+ self.d2 = np.ones((200, 1000), dtype=np.uint8)
+
+ def time_unpackbits(self):
+ np.unpackbits(self.d)
+
+ def time_unpackbits_axis0(self):
+ np.unpackbits(self.d2, axis=0)
+
+ def time_unpackbits_axis1(self):
+ np.unpackbits(self.d2, axis=1)
+
+
+class Indices(Benchmark):
+ def time_indices(self):
+ np.indices((1000, 500))
diff --git a/benchmarks/benchmarks/bench_random.py b/benchmarks/benchmarks/bench_random.py
index 18444b9a1..7ed3e2fa1 100644
--- a/benchmarks/benchmarks/bench_random.py
+++ b/benchmarks/benchmarks/bench_random.py
@@ -3,7 +3,6 @@ from __future__ import absolute_import, division, print_function
from .common import Benchmark
import numpy as np
-from numpy.lib import NumpyVersion
class Random(Benchmark):
@@ -54,6 +53,7 @@ class Randint_dtype(Benchmark):
params = ['bool', 'uint8', 'uint16', 'uint32', 'uint64']
def setup(self, name):
+ from numpy.lib import NumpyVersion
if NumpyVersion(np.__version__) < '1.11.0.dev0':
raise NotImplementedError
diff --git a/doc/release/1.12.0-notes.rst b/doc/release/1.12.0-notes.rst
index b9bc3d197..9889abb42 100644
--- a/doc/release/1.12.0-notes.rst
+++ b/doc/release/1.12.0-notes.rst
@@ -2,14 +2,14 @@
NumPy 1.12.0 Release Notes
==========================
-This release supports Python 2.7 and 3.4 - 3.6.
+This release supports Python 2.7 and 3.4 - 3.6.
Highlights
==========
The NumPy 1.12.0 release contains a large number of fixes and improvements, but
few that stand out above all others. That makes picking out the highlights
somewhat arbitrary but the following may be of particular interest or indicate
-areas likely to have future consequences.
+areas likely to have future consequences.
* Order of operations in ``np.einsum`` can now be optimized for large speed improvements.
* New ``signature`` argument to ``np.vectorize`` for vectorizing with core dimensions.
@@ -43,17 +43,17 @@ Deprecations
============
Assignment of ndarray object's ``data`` attribute
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------------------------
Assigning the 'data' attribute is an inherently unsafe operation as pointed
out in gh-7083. Such a capability will be removed in the future.
Unsafe int casting of the num attribute in ``linspace``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------------------------------
``np.linspace`` now raises DeprecationWarning when num cannot be safely
interpreted as an integer.
Insufficient bit width parameter to ``binary_repr``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------------------
If a 'width' parameter is passed into ``binary_repr`` that is insufficient to
represent the number in base 2 (positive) or 2's complement (negative) form,
the function used to silently ignore the parameter and return a representation
@@ -67,12 +67,12 @@ Future Changes
* In 1.13 NAT will always compare False except for ``NAT != NAT``,
which will be True. In short, NAT will behave like NaN
-* In 1.13 np.average will preserve subclasses, to match the behavior of most
+* In 1.13 ``np.average`` will preserve subclasses, to match the behavior of most
other numpy functions such as np.mean. In particular, this means calls which
returned a scalar may return a 0-d subclass object instead.
Multiple-field manipulation of structured arrays
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------
In 1.13 the behavior of structured arrays involving multiple fields will change
in two ways:
@@ -105,7 +105,7 @@ Compatibility notes
===================
DeprecationWarning to error
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------
* Indexing with floats raises ``IndexError``,
e.g., a[0, 0.0].
@@ -117,15 +117,15 @@ DeprecationWarning to error
e.g., in ``reshape``, ``take``, and specifying reduce axis.
FutureWarning to changed behavior
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------
* ``np.full`` now returns an array of the fill-value's dtype if no dtype is
given, instead of defaulting to float.
-* np.average will emit a warning if the argument is a subclass of ndarray,
+* ``np.average`` will emit a warning if the argument is a subclass of ndarray,
as the subclass will be preserved starting in 1.13. (see Future Changes)
``power`` and ``**`` raise errors for integer to negative integer powers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------------------------------
The previous behavior depended on whether numpy scalar integers or numpy
integer arrays were involved.
@@ -149,18 +149,18 @@ exceptions for the integer units. If you need negative powers, use an inexact
type.
Relaxed stride checking is the default
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------------
This will have some impact on code that assumed that ``F_CONTIGUOUS`` and
``C_CONTIGUOUS`` were mutually exclusive and could be set to determine the
default order for arrays that are now both.
The ``np.percentile`` 'midpoint' interpolation method fixed for exact indices
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------------------------------------
The 'midpoint' interpolator now gives the same result as 'lower' and 'higher' when
the two coincide. Previous behavior of 'lower' + 0.5 is fixed.
``keepdims`` kwarg is passed through to user-class methods
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------------------------------------
numpy functions that take a ``keepdims`` kwarg now pass the value
through to the corresponding methods on ndarray sub-classes. Previously the
``keepdims`` keyword would be silently dropped. These functions now have
@@ -181,17 +181,17 @@ The following functions are changed: ``sum``, ``product``,
``nanstd``
``bitwise_and`` identity changed
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------
The previous identity was 1, it is now -1. See entry in `Improvements`_ for
more explanation.
ma.median warns and returns nan when unmasked invalid values are encountered
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------------------------------------------------------
Similar to unmasked median the masked median `ma.median` now emits a Runtime
warning and returns `NaN` in slices where an unmasked `NaN` is present.
Greater consistancy in ``assert_almost_equal``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------------------------
The precision check for scalars has been changed to match that for arrays. It
is now::
@@ -203,7 +203,7 @@ change in implementation some very delicate tests may fail that did not
fail before.
``NoseTester`` behaviour of warnings during testing
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------------------
When ``raise_warnings="develop"`` is given, all uncaught warnings will now
be considered a test failure. Previously only selected ones were raised.
Warnings which are not caught or raised (mostly when in release mode)
@@ -211,7 +211,7 @@ will be shown once during the test cycle similar to the default python
settings.
``assert_warns`` and ``deprecated`` decorator more specific
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------------------
The ``assert_warns`` function and context manager are now more specific
to the given warning category. This increased specificity leads to them
being handled according to the outer warning settings. This means that
@@ -222,7 +222,7 @@ or raised. See also the new ``suppress_warnings`` context manager.
The same is true for the ``deprecated`` decorator.
C API
-~~~~~
+-----
No changes.
@@ -230,19 +230,19 @@ New Features
============
Writeable keyword argument for ``as_strided``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------------
``np.lib.stride_tricks.as_strided`` now has a ``writeable``
keyword argument. It can be set to False when no write operation
to the returned array is expected to avoid accidental
unpredictable writes.
``axes`` keyword argument for ``rot90``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------
The ``axes`` keyword argument in ``rot90`` determines the plane in which the
array is rotated. It defaults to ``axes=(0,1)`` as in the originial function.
Generalized ``flip``
-~~~~~~~~~~~~~~~~~~~~
+--------------------
``flipud`` and ``fliplr`` reverse the elements of an array along axis=0 and
axis=1 respectively. The newly added ``flip`` function reverses the elements of
an array along any given axis.
@@ -252,13 +252,13 @@ an array along any given axis.
array object.
BLIS support in ``numpy.distutils``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------
Building against the BLAS implementation provided by the BLIS library is now
supported. See the ``[blis]`` section in ``site.cfg.example`` (in the root of
the numpy repo or source distribution).
Hook in ``numpy/__init__.py`` to run distribution-specific checks
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------------------------
Binary distributions of numpy may need to run specific hardware checks or load
specific libraries during numpy initialization. For example, if we are
distributing numpy with a BLAS library that requires SSE2 instructions, we
@@ -270,31 +270,31 @@ file that will remain empty (bar a docstring) in the standard numpy source,
but that can be overwritten by people making binary distributions of numpy.
New nanfunctions ``nancumsum`` and ``nancumprod`` added
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------------------------------
Nan-functions ``nancumsum`` and ``nancumprod`` have been added to
compute ``cumsum`` and ``cumprod`` by ignoring nans.
``np.interp`` can now interpolate complex values
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------
``np.lib.interp(x, xp, fp)`` now allows the interpolated array ``fp``
to be complex and will interpolate at ``complex128`` precision.
New polynomial evaluation function ``polyvalfromroots`` added
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------------------------------------
The new function ``polyvalfromroots`` evaluates a polynomial at given points
from the roots of the polynomial. This is useful for higher order polynomials,
where expansion into polynomial coefficients is inaccurate at machine
precision.
New array creation function ``geomspace`` added
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------
The new function ``geomspace`` generates a geometric sequence. It is similar
to ``logspace``, but with start and stop specified directly:
``geomspace(start, stop)`` behaves the same as
``logspace(log10(start), log10(stop))``.
New context manager for testing warnings
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------------------
A new context manager ``suppress_warnings`` has been added to the testing
utils. This context manager is designed to help reliably test warnings.
Specifically to reliably filter/ignore warnings. Ignoring warnings
@@ -309,14 +309,14 @@ to use the context manager as a decorator which can be useful when
multiple tests give need to hide the same warning.
New masked array functions ``ma.convolve`` and ``ma.correlate`` added
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------------------------------------
These functions wrapped the non-masked versions, but propagate through masked
values. There are two different propagation modes. The default causes masked
values to contaminate the result with masks, but the other mode only outputs
masks if there is no alternative.
New ``float_power`` ufunc
-~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------
The new ``float_power`` ufunc is like the ``power`` function except all
computation is done in a minimum precision of float64. There was a long
discussion on the numpy mailing list of how to treat integers to negative
@@ -325,40 +325,40 @@ always return results of at least float64 precision. The ``float_power``
function implements that option. Note that it does not support object arrays.
``np.loadtxt`` now supports a single integer as ``usecol`` argument
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------------------------------------------
Instead of using ``usecol=(n,)`` to read the nth column of a file
it is now allowed to use ``usecol=n``. Also the error message is
more user friendly when a non-integer is passed as a column index.
Improved automated bin estimators for ``histogram``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------------------
Added 'doane' and 'sqrt' estimators to ``histogram`` via the ``bins``
argument. Added support for range-restricted histograms with automated
bin estimation.
``np.roll`` can now roll multiple axes at the same time
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------------------------------
The ``shift`` and ``axis`` arguments to ``roll`` are now broadcast against each
other, and each specified axis is shifted accordingly.
The ``__complex__`` method has been implemented for the ndarrays
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------------------------------------------
Calling ``complex()`` on a size 1 array will now cast to a python
complex.
``pathlib.Path`` objects now supported
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------------
The standard ``np.load``, ``np.save``, ``np.loadtxt``, ``np.savez``, and similar
functions can now take ``pathlib.Path`` objects as an argument instead of a
filename or open file object.
New ``bits`` attribute for ``np.finfo``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------
This makes ``np.finfo`` consistent with ``np.iinfo`` which already has that
attribute.
New ``signature`` argument to ``np.vectorize``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------------------------
This argument allows for vectorizing user defined functions with core
dimensions, in the style of NumPy's
:ref:`generalized universal functions<c-api.generalized-ufuncs>`. This allows
@@ -368,7 +368,7 @@ vectorized with ``signature='(n),(n)->()'``. See ``np.vectorize`` for full
details.
Emit py3kwarnings for division of integer arrays
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------
To help people migrate their code bases from Python 2 to Python 3, the
python interpreter has a handy option -3, which issues warnings at runtime.
One of its warnings is for integer division::
@@ -385,7 +385,7 @@ With this version, numpy will emit a similar warning::
-c:1: DeprecationWarning: numpy: classic int division
numpy.sctypes now includes bytes on Python3 too
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------
Previously, it included str (bytes) and unicode on Python2, but only str
(unicode) on Python3.
@@ -394,26 +394,26 @@ Improvements
============
``bitwise_and`` identity changed
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------
The previous identity was 1 with the result that all bits except the LSB were
masked out when the reduce method was used. The new identity is -1, which
should work properly on twos complement machines as all bits will be set to
one.
Generalized Ufuncs will now unlock the GIL
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------
Generalized Ufuncs, including most of the linalg module, will now unlock
the Python global interpreter lock.
Caches in `np.fft` are now bounded in total size and item count
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------------------------------
The caches in `np.fft` that speed up successive FFTs of the same length can no
longer grow without bounds. They have been replaced with LRU (least recently
used) caches that automatically evict no longer needed items if either the
memory size or item count limit has been reached.
Improved handling of zero-width string/unicode dtypes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------------
Fixed several interfaces that explicitly disallowed arrays with zero-width
string dtypes (i.e. ``dtype('S0')`` or ``dtype('U0')``, and fixed several
bugs where such dtypes were not handled properly. In particular, changed
@@ -421,12 +421,12 @@ bugs where such dtypes were not handled properly. In particular, changed
``dtype('S1')`` (and likewise for unicode) when creating new arrays.
Integer ufuncs vectorized with AVX2
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------
If the cpu supports it at runtime the basic integer ufuncs now use AVX2
instructions. This feature is currently only available when compiled with GCC.
Order of operations optimization in ``np.einsum``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------------------------
``np.einsum`` now supports the ``optimize`` argument which will optimize the
order of contraction. For example, ``np.einsum`` would complete the chain dot
example ``np.einsum(‘ij,jk,kl->il’, a, b, c)`` in a single pass which would
@@ -437,14 +437,14 @@ been applied to the general einsum summation notation. See ``np.einsum_path``
for more details.
quicksort has been changed to an introsort
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------
The quicksort kind of ``np.sort`` and ``np.argsort`` is now an introsort which
is regular quicksort but changing to a heapsort when not enough progress is
made. This retains the good quicksort performance while changing the worst case
runtime from ``O(N^2)`` to ``O(N*log(N))``.
``ediff1d`` improved performance and subclass handling
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------------
The ediff1d function uses an array instead on a flat iterator for the
subtraction. When to_begin or to_end is not None, the subtraction is performed
in place to eliminate a copy operation. A side effect is that certain
@@ -453,9 +453,9 @@ array is created, wrapped, and then begin and end values are set, instead of
using concatenate.
Improved precision of ``ndarray.mean`` for float16 arrays
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------------------------------------------------
The computation of the mean of float16 arrays is now carried out in float32 for
-improved precision. This should be useful in packages such as scikit-learn
+improved precision. This should be useful in packages such as Theano
where the precision of float16 is adequate and its smaller footprint is
desireable.
@@ -464,7 +464,7 @@ Changes
=======
All array-like methods are now called with keyword arguments in fromnumeric.py
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------------------------------------
Internally, many array-like methods in fromnumeric.py were being called with
positional arguments instead of keyword arguments as their external signatures
were doing. This caused a complication in the downstream 'pandas' library
@@ -472,7 +472,7 @@ that encountered an issue with 'numpy' compatibility. Now, all array-like
methods in this module are called with keyword arguments instead.
Operations on np.memmap objects return numpy arrays in most cases
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------------------------
Previously operations on a memmap object would misleadingly return a memmap
instance even if the result was actually not memmapped. For example,
``arr + 1`` or ``arr + arr`` would return memmap instances, although no memory
@@ -483,7 +483,7 @@ Also, reduction of a memmap (e.g. ``.sum(axis=None``) now returns a numpy
scalar instead of a 0d memmap.
stacklevel of warnings increased
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------
The stacklevel for python based warnings was increased so that most warnings
will report the offending line of the user code instead of the line the
warning itself is given. Passing of stacklevel is now tested to ensure that
@@ -495,561 +495,572 @@ python versions before 3.4, this can cause warnings to appear that were falsely
ignored before, which may be surprising especially in test suits.
-
-Contributors to maintenance/1.12.x
-==================================
+Contributors
+============
A total of 139 people contributed to this release. People with a "+" by their
names contributed a patch for the first time.
-- Aditya Panchal
-- Ales Erjavec +
-- Alex Griffing
-- Alexandr Shadchin +
-- Alistair Muldal
-- Allan Haldane
-- Amit Aronovitch +
-- Andrei Kucharavy +
-- Antony Lee
-- Antti Kaihola +
-- Arne de Laat +
-- Auke Wiggers +
-- AustereCuriosity +
-- Badhri Narayanan Krishnakumar +
-- Ben North +
-- Ben Rowland +
-- Bertrand Lefebvre
-- Boxiang Sun
-- CJ Carey
-- Charles Harris
-- Christoph Gohlke
-- Daniel Ching +
-- Daniel Rasmussen +
-- Daniel Smith +
-- David Schaich +
-- Denis Alevi +
-- Devin Jeanpierre +
-- Dmitry Odzerikho
-- Dongjoon Hyun +
-- Edward Richards +
-- Ekaterina Tuzova +
-- Emilien Kofman +
-- Endolith
-- Eren Sezener +
-- Eric Moore
-- Eric Quintero +
-- Eric Wieser +
-- Erik M. Bray
-- Frederic Bastien +
-- Friedrich Dunne +
-- Gerrit Holl
-- Golnaz Irannejad +
-- Graham Markall +
-- Greg Knoll +
-- Greg Young
-- Gustavo Serra Scalet +
-- Ines Wichert +
-- Irvin Probst +
-- Jaime Fernandez
-- James Sanders +
-- Jan David Mol +
-- Jan Schlüter
-- Jeremy Tuloup +
-- John Kirkham
-- John Zwinck +
-- Jonathan Helmus
-- Joseph Fox-Rabinovitz
-- Josh Wilson +
-- Joshua Warner +
-- Julian Taylor
-- Ka Wo Chen +
-- Kamil Rytarowski +
-- Kelsey Jordahl +
-- Kevin Deldycke +
-- Khaled Ben Abdallah Okuda +
-- Lion Krischer +
-- Loïc Estève +
-- Luca Mussi +
-- Mads Ohm Larsen +
-- Manoj Kumar +
-- Mario Emmenlauer +
-- Marshall Bockrath-Vandegrift +
-- Marshall Ward +
-- Marten van Kerkwijk
-- Mathieu Lamarre +
-- Matthew Brett
-- Matthew Harrigan +
-- Matthias Geier
-- Matti Picus +
-- Meet Udeshi +
-- Michael Felt +
-- Michael Goerz +
-- Michael Martin +
-- Michael Seifert +
-- Mike Nolta +
-- Nathaniel Beaver +
-- Nathaniel J. Smith
-- Naveen Arunachalam +
-- Nick Papior
-- Nikola Forró +
-- Oleksandr Pavlyk +
-- Olivier Grisel
-- Oren Amsalem +
-- Pauli Virtanen
-- Pavel Potocek +
-- Pedro Lacerda +
-- Peter Creasey +
-- Phil Elson +
-- Philip Gura +
-- Phillip J. Wolfram +
-- Pierre de Buyl +
-- Raghav RV +
-- Ralf Gommers
-- Ray Donnelly +
-- Rehas Sachdeva
-- Rob Malouf +
-- Robert Kern
-- Samuel St-Jean
-- Sanchez Gonzalez Alvaro +
-- Saurabh Mehta +
-- Scott Sanderson +
-- Sebastian Berg
-- Shayan Pooya +
-- Shota Kawabuchi +
-- Simon Conseil
-- Simon Gibbons
-- Sorin Sbarnea +
-- Stefan van der Walt
-- Stephan Hoyer
-- Steven J Kern +
-- Stuart Archibald
-- Tadeu Manoel +
-- Takuya Akiba +
-- Thomas A Caswell
-- Tom Bird +
-- Tony Kelman +
-- Toshihiro Kamishima +
-- Valentin Valls +
-- Varun Nayyar
-- Victor Stinner +
-- Warren Weckesser
-- Wendell Smith
-- Wojtek Ruszczewski +
-- Xavier Abellan Ecija +
-- Yaroslav Halchenko
-- Yash Shah +
-- Yinon Ehrlich +
-- Yu Feng +
-- nevimov +
-
-Pull requests merged for maintenance/1.12.x
-===========================================
-
-A total of 406 pull requests were merged for this release.
-
-- `#4073 <https://github.com/numpy/numpy/pull/4073>`__: BUG: change real output checking to test if all imaginary parts...
-- `#4619 <https://github.com/numpy/numpy/pull/4619>`__: BUG : np.sum silently drops keepdims for sub-classes of ndarray
-- `#5488 <https://github.com/numpy/numpy/pull/5488>`__: ENH: add `contract`: optimizing numpy's einsum expression
-- `#5706 <https://github.com/numpy/numpy/pull/5706>`__: ENH: make some masked array methods behave more like ndarray...
-- `#5822 <https://github.com/numpy/numpy/pull/5822>`__: Allow many distributions to have a scale of 0.
-- `#6054 <https://github.com/numpy/numpy/pull/6054>`__: WIP: MAINT: Add deprecation warning to views of multi-field indexes
-- `#6298 <https://github.com/numpy/numpy/pull/6298>`__: Check lower base limit in base_repr.
-- `#6430 <https://github.com/numpy/numpy/pull/6430>`__: Fix issues with zero-width string fields
-- `#6656 <https://github.com/numpy/numpy/pull/6656>`__: ENH: usecols now accepts an int when only one column has to be...
-- `#6660 <https://github.com/numpy/numpy/pull/6660>`__: Added pathlib support for several functions
-- `#6872 <https://github.com/numpy/numpy/pull/6872>`__: ENH: linear interpolation of complex values in lib.interp
-- `#6997 <https://github.com/numpy/numpy/pull/6997>`__: MAINT: Simplify mtrand.pyx helpers
-- `#7003 <https://github.com/numpy/numpy/pull/7003>`__: BUG: Fix string copying for np.place
-- `#7026 <https://github.com/numpy/numpy/pull/7026>`__: DOC: Clarify behavior in np.random.uniform
-- `#7055 <https://github.com/numpy/numpy/pull/7055>`__: BUG: One Element Array Inputs Return Scalars in np.random
-- `#7063 <https://github.com/numpy/numpy/pull/7063>`__: REL: Update master branch after 1.11.x branch has been made.
-- `#7073 <https://github.com/numpy/numpy/pull/7073>`__: DOC: Update the 1.11.0 release notes.
-- `#7076 <https://github.com/numpy/numpy/pull/7076>`__: MAINT: Update the git .mailmap file.
-- `#7082 <https://github.com/numpy/numpy/pull/7082>`__: TST, DOC: Added Broadcasting Tests in test_random.py
-- `#7087 <https://github.com/numpy/numpy/pull/7087>`__: BLD: fix compilation on non glibc-Linuxes
-- `#7088 <https://github.com/numpy/numpy/pull/7088>`__: BUG: Have `norm` cast non-floating point arrays to 64-bit float...
-- `#7090 <https://github.com/numpy/numpy/pull/7090>`__: ENH: Added 'doane' and 'sqrt' estimators to np.histogram in numpy.function_base
-- `#7091 <https://github.com/numpy/numpy/pull/7091>`__: Revert "BLD: fix compilation on non glibc-Linuxes"
-- `#7092 <https://github.com/numpy/numpy/pull/7092>`__: BLD: fix compilation on non glibc-Linuxes
-- `#7099 <https://github.com/numpy/numpy/pull/7099>`__: TST: Suppressed warnings
-- `#7102 <https://github.com/numpy/numpy/pull/7102>`__: MAINT: Removed conditionals that are always false in datetime_strings.c
-- `#7105 <https://github.com/numpy/numpy/pull/7105>`__: DEP: Deprecate as_strided returning a writable array as default
-- `#7109 <https://github.com/numpy/numpy/pull/7109>`__: DOC: update Python versions requirements in the install docs
-- `#7114 <https://github.com/numpy/numpy/pull/7114>`__: MAINT: Fix typos in docs
-- `#7116 <https://github.com/numpy/numpy/pull/7116>`__: TST: Fixed f2py test for win32 virtualenv
-- `#7118 <https://github.com/numpy/numpy/pull/7118>`__: TST: Fixed f2py test for non-versioned python executables
-- `#7119 <https://github.com/numpy/numpy/pull/7119>`__: BUG: Fixed mingw.lib error
-- `#7125 <https://github.com/numpy/numpy/pull/7125>`__: DOC: Updated documentation wording and examples for np.percentile.
-- `#7129 <https://github.com/numpy/numpy/pull/7129>`__: BUG: Fixed 'midpoint' interpolation of np.percentile in odd cases.
-- `#7131 <https://github.com/numpy/numpy/pull/7131>`__: Fix setuptools sdist
-- `#7133 <https://github.com/numpy/numpy/pull/7133>`__: ENH: savez: temporary file alongside with target file and improve...
-- `#7134 <https://github.com/numpy/numpy/pull/7134>`__: MAINT: Fix some typos in a code string and comments
-- `#7141 <https://github.com/numpy/numpy/pull/7141>`__: BUG: Unpickled void scalars should be contiguous
-- `#7144 <https://github.com/numpy/numpy/pull/7144>`__: MAINT: Change `call_fortran` into `callfortran` in comments.
-- `#7145 <https://github.com/numpy/numpy/pull/7145>`__: BUG: Fixed regressions in np.piecewise in ref to #5737 and #5729.
-- `#7147 <https://github.com/numpy/numpy/pull/7147>`__: Temporarily disable __numpy_ufunc__
-- `#7148 <https://github.com/numpy/numpy/pull/7148>`__: ENH,TST: Bump stacklevel and add tests for warnings
-- `#7149 <https://github.com/numpy/numpy/pull/7149>`__: TST: Add missing suffix to temppath manager
-- `#7152 <https://github.com/numpy/numpy/pull/7152>`__: BUG: mode kwargs passed as unicode to np.pad raises an exception
-- `#7156 <https://github.com/numpy/numpy/pull/7156>`__: BUG: Reascertain that linspace respects ndarray subclasses in...
-- `#7167 <https://github.com/numpy/numpy/pull/7167>`__: DOC: Update Wikipedia references for mtrand.pyx
-- `#7171 <https://github.com/numpy/numpy/pull/7171>`__: TST: Fixed f2py test for Anaconda non-win32
-- `#7174 <https://github.com/numpy/numpy/pull/7174>`__: DOC: Fix broken pandas link in release notes
-- `#7177 <https://github.com/numpy/numpy/pull/7177>`__: ENH: added axis param for np.count_nonzero
-- `#7178 <https://github.com/numpy/numpy/pull/7178>`__: BUG: Fix binary_repr for negative numbers
-- `#7180 <https://github.com/numpy/numpy/pull/7180>`__: BUG: Fixed previous attempt to fix dimension mismatch in nanpercentile
-- `#7181 <https://github.com/numpy/numpy/pull/7181>`__: DOC: Updated minor typos in function_base.py and test_function_base.py
-- `#7191 <https://github.com/numpy/numpy/pull/7191>`__: DOC: add vstack, hstack, dstack reference to stack documentation.
-- `#7193 <https://github.com/numpy/numpy/pull/7193>`__: MAINT: Removed supurious assert in histogram estimators
-- `#7194 <https://github.com/numpy/numpy/pull/7194>`__: BUG: Raise a quieter `MaskedArrayFutureWarning` for mask changes.
-- `#7195 <https://github.com/numpy/numpy/pull/7195>`__: STY: Drop some trailing spaces in `numpy.ma.core`.
-- `#7196 <https://github.com/numpy/numpy/pull/7196>`__: Revert "DOC: add vstack, hstack, dstack reference to stack documentation."
-- `#7197 <https://github.com/numpy/numpy/pull/7197>`__: TST: Pin virtualenv used on Travis CI.
-- `#7198 <https://github.com/numpy/numpy/pull/7198>`__: ENH: Unlock the GIL for gufuncs
-- `#7199 <https://github.com/numpy/numpy/pull/7199>`__: MAINT: Cleanup for histogram bin estimator selection
-- `#7201 <https://github.com/numpy/numpy/pull/7201>`__: Raise IOError on not a file in python2
-- `#7202 <https://github.com/numpy/numpy/pull/7202>`__: MAINT: Made `iterable` return a boolean
-- `#7209 <https://github.com/numpy/numpy/pull/7209>`__: TST: Bump `virtualenv` to 14.0.6
-- `#7211 <https://github.com/numpy/numpy/pull/7211>`__: DOC: Fix fmin examples
-- `#7215 <https://github.com/numpy/numpy/pull/7215>`__: MAINT: Use PySlice_GetIndicesEx instead of custom reimplementation
-- `#7229 <https://github.com/numpy/numpy/pull/7229>`__: ENH: implement __complex__
-- `#7231 <https://github.com/numpy/numpy/pull/7231>`__: MRG: allow distributors to run custom init
-- `#7232 <https://github.com/numpy/numpy/pull/7232>`__: BLD: Switch order of test for lapack_mkl and openblas_lapack
-- `#7239 <https://github.com/numpy/numpy/pull/7239>`__: DOC: Removed residual merge markup from previous commit
-- `#7240 <https://github.com/numpy/numpy/pull/7240>`__: Change 'pubic' to 'public'.
-- `#7241 <https://github.com/numpy/numpy/pull/7241>`__: MAINT: update doc/sphinxext to numpydoc 0.6.0, and fix up some...
-- `#7243 <https://github.com/numpy/numpy/pull/7243>`__: ENH: Adding support to the range keyword for estimation of the...
-- `#7246 <https://github.com/numpy/numpy/pull/7246>`__: DOC: metion writeable keyword in as_strided in release notes
-- `#7247 <https://github.com/numpy/numpy/pull/7247>`__: TST: Fail quickly on AppVeyor for superseded PR builds
-- `#7248 <https://github.com/numpy/numpy/pull/7248>`__: DOC: remove link to documentation wiki editor from HOWTO_DOCUMENT.
-- `#7250 <https://github.com/numpy/numpy/pull/7250>`__: DOC,REL: Update 1.11.0 notes.
-- `#7251 <https://github.com/numpy/numpy/pull/7251>`__: BUG: only benchmark complex256 if it exists
-- `#7252 <https://github.com/numpy/numpy/pull/7252>`__: Forward port a fix and enhancement from 1.11.x
-- `#7253 <https://github.com/numpy/numpy/pull/7253>`__: DOC: note in h/v/dstack points users to stack/concatenate
-- `#7254 <https://github.com/numpy/numpy/pull/7254>`__: BUG: Enforce dtype for randint singletons
-- `#7256 <https://github.com/numpy/numpy/pull/7256>`__: MAINT: Use `is None` or `is not None` instead of `== None` or...
-- `#7257 <https://github.com/numpy/numpy/pull/7257>`__: DOC: Fix mismatched variable names in docstrings.
-- `#7258 <https://github.com/numpy/numpy/pull/7258>`__: ENH: Make numpy floor_divide and remainder agree with Python...
-- `#7260 <https://github.com/numpy/numpy/pull/7260>`__: BUG/TST: Fix #7259, do not "force scalar" for already scalar...
-- `#7261 <https://github.com/numpy/numpy/pull/7261>`__: Added self to mailmap
-- `#7266 <https://github.com/numpy/numpy/pull/7266>`__: BUG: Segfault for classes with deceptive __len__
-- `#7268 <https://github.com/numpy/numpy/pull/7268>`__: ENH: add geomspace function
-- `#7274 <https://github.com/numpy/numpy/pull/7274>`__: BUG: Preserve array order in np.delete
-- `#7275 <https://github.com/numpy/numpy/pull/7275>`__: DEP: Warn about assigning 'data' attribute of ndarray
-- `#7276 <https://github.com/numpy/numpy/pull/7276>`__: DOC: apply_along_axis missing whitespace inserted (before colon)
-- `#7278 <https://github.com/numpy/numpy/pull/7278>`__: BUG: Make returned unravel_index arrays writeable
-- `#7279 <https://github.com/numpy/numpy/pull/7279>`__: TST: Fixed elements being shuffled
-- `#7280 <https://github.com/numpy/numpy/pull/7280>`__: MAINT: Remove redundant trailing semicolons.
-- `#7285 <https://github.com/numpy/numpy/pull/7285>`__: BUG: Make Randint Backwards Compatible with Pandas
-- `#7286 <https://github.com/numpy/numpy/pull/7286>`__: MAINT: Fix typos in docs/comments of `ma` and `polynomial` modules.
-- `#7292 <https://github.com/numpy/numpy/pull/7292>`__: Clarify error on repr failure in assert_equal.
-- `#7294 <https://github.com/numpy/numpy/pull/7294>`__: ENH: add support for BLIS to numpy.distutils
-- `#7295 <https://github.com/numpy/numpy/pull/7295>`__: DOC: understanding code and getting started section to dev doc
-- `#7296 <https://github.com/numpy/numpy/pull/7296>`__: Revert part of #3907 which incorrectly propogated MaskedArray...
-- `#7299 <https://github.com/numpy/numpy/pull/7299>`__: DOC: Fix mismatched variable names in docstrings.
-- `#7300 <https://github.com/numpy/numpy/pull/7300>`__: DOC: dev: stop recommending keeping local master updated with...
-- `#7301 <https://github.com/numpy/numpy/pull/7301>`__: DOC: Update release notes
-- `#7305 <https://github.com/numpy/numpy/pull/7305>`__: BUG: Remove data race in mtrand: two threads could mutate the...
-- `#7307 <https://github.com/numpy/numpy/pull/7307>`__: DOC: Missing some characters in link.
-- `#7308 <https://github.com/numpy/numpy/pull/7308>`__: BUG: Incrementing the wrong reference on return
-- `#7310 <https://github.com/numpy/numpy/pull/7310>`__: STY: Fix GitHub rendering of ordered lists >9
-- `#7311 <https://github.com/numpy/numpy/pull/7311>`__: ENH: Make _pointer_type_cache functional
-- `#7313 <https://github.com/numpy/numpy/pull/7313>`__: DOC: corrected grammatical error in quickstart doc
-- `#7325 <https://github.com/numpy/numpy/pull/7325>`__: BUG, MAINT: Improve fromnumeric.py interface for downstream compatibility
-- `#7328 <https://github.com/numpy/numpy/pull/7328>`__: DEP: Deprecated using a float index in linspace
-- `#7331 <https://github.com/numpy/numpy/pull/7331>`__: Add comment, TST: fix MemoryError on win32
-- `#7332 <https://github.com/numpy/numpy/pull/7332>`__: Check for no solution in np.irr Fixes #6744
-- `#7338 <https://github.com/numpy/numpy/pull/7338>`__: TST: Install `pytz` in the CI.
-- `#7340 <https://github.com/numpy/numpy/pull/7340>`__: DOC: Fixed math rendering in tensordot docs.
-- `#7341 <https://github.com/numpy/numpy/pull/7341>`__: TST: Add test for #6469
-- `#7344 <https://github.com/numpy/numpy/pull/7344>`__: DOC: Fix more typos in docs and comments.
-- `#7346 <https://github.com/numpy/numpy/pull/7346>`__: Generalized flip
-- `#7347 <https://github.com/numpy/numpy/pull/7347>`__: ENH Generalized rot90
-- `#7348 <https://github.com/numpy/numpy/pull/7348>`__: Maint: Removed extra space from `ureduce`
-- `#7349 <https://github.com/numpy/numpy/pull/7349>`__: MAINT: Hide nan warnings for masked internal MA computations
-- `#7350 <https://github.com/numpy/numpy/pull/7350>`__: BUG: MA ufuncs should set mask to False, not array([False])
-- `#7351 <https://github.com/numpy/numpy/pull/7351>`__: TST: Fix some MA tests to avoid looking at the .data attribute
-- `#7358 <https://github.com/numpy/numpy/pull/7358>`__: BUG: pull request related to the issue #7353
-- `#7359 <https://github.com/numpy/numpy/pull/7359>`__: Update 7314, DOC: Clarify valid integer range for random.seed...
-- `#7361 <https://github.com/numpy/numpy/pull/7361>`__: MAINT: Fix copy and paste oversight.
-- `#7363 <https://github.com/numpy/numpy/pull/7363>`__: ENH: Make no unshare mask future warnings less noisy
-- `#7366 <https://github.com/numpy/numpy/pull/7366>`__: TST: fix #6542, add tests to check non-iterable argument raises...
-- `#7373 <https://github.com/numpy/numpy/pull/7373>`__: ENH: Add bitwise_and identity
-- `#7378 <https://github.com/numpy/numpy/pull/7378>`__: added NumPy logo and separator
-- `#7382 <https://github.com/numpy/numpy/pull/7382>`__: MAINT: cleanup np.average
-- `#7385 <https://github.com/numpy/numpy/pull/7385>`__: DOC: note about wheels / windows wheels for pypi
-- `#7386 <https://github.com/numpy/numpy/pull/7386>`__: Added label icon to Travis status
-- `#7397 <https://github.com/numpy/numpy/pull/7397>`__: BUG: incorrect type for objects whose __len__ fails
-- `#7398 <https://github.com/numpy/numpy/pull/7398>`__: DOC: fix typo
-- `#7404 <https://github.com/numpy/numpy/pull/7404>`__: Use PyMem_RawMalloc on Python 3.4 and newer
-- `#7406 <https://github.com/numpy/numpy/pull/7406>`__: ENH ufunc called on memmap return a ndarray
-- `#7407 <https://github.com/numpy/numpy/pull/7407>`__: BUG: Fix decref before incref for in-place accumulate
-- `#7410 <https://github.com/numpy/numpy/pull/7410>`__: DOC: add nanprod to the list of math routines
-- `#7414 <https://github.com/numpy/numpy/pull/7414>`__: Tweak corrcoef
-- `#7415 <https://github.com/numpy/numpy/pull/7415>`__: DOC: Documention fixes
-- `#7416 <https://github.com/numpy/numpy/pull/7416>`__: BUG: Incorrect handling of range in `histogram` with automatic...
-- `#7418 <https://github.com/numpy/numpy/pull/7418>`__: DOC: Minor typo fix, hermefik -> hermefit.
-- `#7421 <https://github.com/numpy/numpy/pull/7421>`__: ENH: adds np.nancumsum and np.nancumprod
-- `#7423 <https://github.com/numpy/numpy/pull/7423>`__: BUG: Ongoing fixes to PR#7416
-- `#7430 <https://github.com/numpy/numpy/pull/7430>`__: DOC: Update 1.11.0-notes.
-- `#7433 <https://github.com/numpy/numpy/pull/7433>`__: MAINT: FutureWarning for changes to np.average subclass handling
-- `#7437 <https://github.com/numpy/numpy/pull/7437>`__: np.full now defaults to the filling value's dtype.
-- `#7438 <https://github.com/numpy/numpy/pull/7438>`__: Allow rolling multiple axes at the same time.
-- `#7439 <https://github.com/numpy/numpy/pull/7439>`__: BUG: Do not try sequence repeat unless necessary
-- `#7442 <https://github.com/numpy/numpy/pull/7442>`__: MANT: Simplify diagonal length calculation logic
-- `#7445 <https://github.com/numpy/numpy/pull/7445>`__: BUG: reference count leak in bincount, fixes #6805
-- `#7446 <https://github.com/numpy/numpy/pull/7446>`__: DOC: ndarray typo fix
-- `#7447 <https://github.com/numpy/numpy/pull/7447>`__: BUG: scalar integer negative powers gave wrong results.
-- `#7448 <https://github.com/numpy/numpy/pull/7448>`__: DOC: array "See also" link to full and full_like instead of fill
-- `#7456 <https://github.com/numpy/numpy/pull/7456>`__: BUG: int overflow in reshape, fixes #7455, fixes #7293
-- `#7463 <https://github.com/numpy/numpy/pull/7463>`__: BUG: fix array too big error for wide dtypes.
-- `#7466 <https://github.com/numpy/numpy/pull/7466>`__: BUG: segfault inplace object reduceat, fixes #7465
-- `#7468 <https://github.com/numpy/numpy/pull/7468>`__: BUG: more on inplace reductions, fixes #615
-- `#7469 <https://github.com/numpy/numpy/pull/7469>`__: MAINT: Update git .mailmap
-- `#7472 <https://github.com/numpy/numpy/pull/7472>`__: MAINT: Update .mailmap.
-- `#7477 <https://github.com/numpy/numpy/pull/7477>`__: MAINT: Yet more .mailmap updates for recent contributors.
-- `#7481 <https://github.com/numpy/numpy/pull/7481>`__: BUG: Fix segfault in PyArray_OrderConverter
-- `#7482 <https://github.com/numpy/numpy/pull/7482>`__: BUG: Memory Leak in _GenericBinaryOutFunction
-- `#7489 <https://github.com/numpy/numpy/pull/7489>`__: Faster real_if_close.
-- `#7491 <https://github.com/numpy/numpy/pull/7491>`__: DOC: Update subclassing doc regarding downstream compatibility
-- `#7496 <https://github.com/numpy/numpy/pull/7496>`__: BUG: don't use pow for integer power ufunc loops.
-- `#7504 <https://github.com/numpy/numpy/pull/7504>`__: DOC: remove "arr" from keepdims docstrings
-- `#7505 <https://github.com/numpy/numpy/pull/7505>`__: MAIN: fix to #7382, make scl in np.average writeable
-- `#7507 <https://github.com/numpy/numpy/pull/7507>`__: MAINT: Remove nose.SkipTest import.
-- `#7508 <https://github.com/numpy/numpy/pull/7508>`__: DOC: link frompyfunc and vectorize
-- `#7511 <https://github.com/numpy/numpy/pull/7511>`__: numpy.power(0, 0) should return 1
-- `#7515 <https://github.com/numpy/numpy/pull/7515>`__: BUG: MaskedArray.count treats negative axes incorrectly
-- `#7518 <https://github.com/numpy/numpy/pull/7518>`__: BUG: Extend glibc complex trig functions blacklist to glibc <...
-- `#7521 <https://github.com/numpy/numpy/pull/7521>`__: DOC: rephrase writeup of memmap changes
-- `#7522 <https://github.com/numpy/numpy/pull/7522>`__: BUG: Fixed iteration over additional bad commands
-- `#7526 <https://github.com/numpy/numpy/pull/7526>`__: DOC: Removed an extra `:const:`
-- `#7529 <https://github.com/numpy/numpy/pull/7529>`__: BUG: Floating exception with invalid axis in np.lexsort
-- `#7534 <https://github.com/numpy/numpy/pull/7534>`__: MAINT: Update setup.py to reflect supported python versions.
-- `#7536 <https://github.com/numpy/numpy/pull/7536>`__: MAINT: Always use PyCapsule instead of PyCObject in mtrand.pyx
-- `#7539 <https://github.com/numpy/numpy/pull/7539>`__: MAINT: Cleanup of random stuff
-- `#7549 <https://github.com/numpy/numpy/pull/7549>`__: BUG: allow graceful recovery for no Liux compiler
-- `#7562 <https://github.com/numpy/numpy/pull/7562>`__: BUG: Fix test_from_object_array_unicode (test_defchararray.TestBasic)…
-- `#7565 <https://github.com/numpy/numpy/pull/7565>`__: BUG: Fix test_ctypeslib and test_indexing for debug interpreter
-- `#7566 <https://github.com/numpy/numpy/pull/7566>`__: MAINT: use manylinux1 wheel for cython
-- `#7568 <https://github.com/numpy/numpy/pull/7568>`__: Fix a false positive OverflowError in Python 3.x when value above...
-- `#7579 <https://github.com/numpy/numpy/pull/7579>`__: DOC: clarify purpose of Attributes section
-- `#7584 <https://github.com/numpy/numpy/pull/7584>`__: BUG: fixes #7572, percent in path
-- `#7586 <https://github.com/numpy/numpy/pull/7586>`__: Make np.ma.take works on scalars
-- `#7587 <https://github.com/numpy/numpy/pull/7587>`__: BUG: linalg.norm(): Don't convert object arrays to float
-- `#7598 <https://github.com/numpy/numpy/pull/7598>`__: Cast array size to int64 when loading from archive
-- `#7602 <https://github.com/numpy/numpy/pull/7602>`__: DOC: Remove isreal and iscomplex from ufunc list
-- `#7605 <https://github.com/numpy/numpy/pull/7605>`__: DOC: fix incorrect Gamma distribution parameterization comments
-- `#7609 <https://github.com/numpy/numpy/pull/7609>`__: BUG: Fix TypeError when raising TypeError
-- `#7611 <https://github.com/numpy/numpy/pull/7611>`__: ENH: expose test runner raise_warnings option
-- `#7614 <https://github.com/numpy/numpy/pull/7614>`__: BLD: Avoid using os.spawnve in favor of os.spawnv in exec_command
-- `#7618 <https://github.com/numpy/numpy/pull/7618>`__: BUG: distance arg of np.gradient must be scalar, fix docstring
-- `#7626 <https://github.com/numpy/numpy/pull/7626>`__: DOC: RST definition list fixes
-- `#7627 <https://github.com/numpy/numpy/pull/7627>`__: MAINT: unify tup processing, move tup use to after all PyTuple_SetItem...
-- `#7630 <https://github.com/numpy/numpy/pull/7630>`__: MAINT: add ifdef around PyDictProxy_Check macro
-- `#7631 <https://github.com/numpy/numpy/pull/7631>`__: MAINT: linalg: fix comment, simplify math
-- `#7634 <https://github.com/numpy/numpy/pull/7634>`__: BLD: correct C compiler customization in system_info.py Closes...
-- `#7635 <https://github.com/numpy/numpy/pull/7635>`__: BUG: ma.median alternate fix for #7592
-- `#7636 <https://github.com/numpy/numpy/pull/7636>`__: MAINT: clean up testing.assert_raises_regexp, 2.6-specific code...
-- `#7637 <https://github.com/numpy/numpy/pull/7637>`__: MAINT: clearer exception message when importing multiarray fails.
-- `#7639 <https://github.com/numpy/numpy/pull/7639>`__: TST: fix a set of test errors in master.
-- `#7643 <https://github.com/numpy/numpy/pull/7643>`__: DOC : minor changes to linspace docstring
-- `#7651 <https://github.com/numpy/numpy/pull/7651>`__: BUG: one to any power is still 1. Broken edgecase for int arrays
-- `#7655 <https://github.com/numpy/numpy/pull/7655>`__: BLD: Remove Intel compiler flag -xSSE4.2
-- `#7658 <https://github.com/numpy/numpy/pull/7658>`__: BUG: fix incorrect printing of 1D masked arrays
-- `#7659 <https://github.com/numpy/numpy/pull/7659>`__: BUG: Temporary fix for str(mvoid) for object field types
-- `#7664 <https://github.com/numpy/numpy/pull/7664>`__: BUG: Fix unicode with byte swap transfer and copyswap
-- `#7667 <https://github.com/numpy/numpy/pull/7667>`__: Restore histogram consistency
-- `#7668 <https://github.com/numpy/numpy/pull/7668>`__: ENH: Do not check the type of module.__dict__ explicit in test.
-- `#7669 <https://github.com/numpy/numpy/pull/7669>`__: BUG: boolean assignment no GIL release when transfer needs API
-- `#7673 <https://github.com/numpy/numpy/pull/7673>`__: DOC: Create Numpy 1.11.1 release notes.
-- `#7675 <https://github.com/numpy/numpy/pull/7675>`__: BUG: fix handling of right edge of final bin.
-- `#7678 <https://github.com/numpy/numpy/pull/7678>`__: BUG: Fix np.clip bug NaN handling for Visual Studio 2015
-- `#7679 <https://github.com/numpy/numpy/pull/7679>`__: MAINT: Fix up C++ comment in arraytypes.c.src.
-- `#7681 <https://github.com/numpy/numpy/pull/7681>`__: DOC: Update 1.11.1 release notes.
-- `#7686 <https://github.com/numpy/numpy/pull/7686>`__: ENH: Changing FFT cache to a bounded LRU cache
-- `#7688 <https://github.com/numpy/numpy/pull/7688>`__: DOC: fix broken genfromtxt examples in user guide. Closes gh-7662.
-- `#7689 <https://github.com/numpy/numpy/pull/7689>`__: BENCH: add correlate/convolve benchmarks.
-- `#7696 <https://github.com/numpy/numpy/pull/7696>`__: DOC: update wheel build / upload instructions
-- `#7699 <https://github.com/numpy/numpy/pull/7699>`__: BLD: preserve library order
-- `#7704 <https://github.com/numpy/numpy/pull/7704>`__: ENH: Add bits attribute to np.finfo
-- `#7712 <https://github.com/numpy/numpy/pull/7712>`__: BUG: Fix race condition with new FFT cache
-- `#7715 <https://github.com/numpy/numpy/pull/7715>`__: BUG: Remove memory leak in np.place
-- `#7719 <https://github.com/numpy/numpy/pull/7719>`__: BUG: Fix segfault in np.random.shuffle for arrays of different...
-- `#7723 <https://github.com/numpy/numpy/pull/7723>`__: Change mkl_info.dir_env_var from MKL to MKLROOT
-- `#7727 <https://github.com/numpy/numpy/pull/7727>`__: DOC: Corrections in Datetime Units-arrays.datetime.rst
-- `#7729 <https://github.com/numpy/numpy/pull/7729>`__: DOC: fix typo in savetxt docstring (closes #7620)
-- `#7733 <https://github.com/numpy/numpy/pull/7733>`__: Update 7525, DOC: Fix order='A' docs of np.array.
-- `#7734 <https://github.com/numpy/numpy/pull/7734>`__: Update 7542, ENH: Add `polyrootval` to numpy.polynomial
-- `#7735 <https://github.com/numpy/numpy/pull/7735>`__: BUG: fix issue on OS X with Python 3.x where npymath.ini was...
-- `#7739 <https://github.com/numpy/numpy/pull/7739>`__: DOC: Mention the changes of #6430 in the release notes.
-- `#7740 <https://github.com/numpy/numpy/pull/7740>`__: DOC: add reference to poisson rng
-- `#7743 <https://github.com/numpy/numpy/pull/7743>`__: Update 7476, DEP: deprecate Numeric-style typecodes, closes #2148
-- `#7744 <https://github.com/numpy/numpy/pull/7744>`__: DOC: Remove "ones_like" from ufuncs list (it is not)
-- `#7746 <https://github.com/numpy/numpy/pull/7746>`__: DOC: Clarify the effect of rcond in numpy.linalg.lstsq.
-- `#7747 <https://github.com/numpy/numpy/pull/7747>`__: Update 7672, BUG: Make sure we don't divide by zero
-- `#7748 <https://github.com/numpy/numpy/pull/7748>`__: DOC: Update float32 mean example in docstring
-- `#7754 <https://github.com/numpy/numpy/pull/7754>`__: Update 7612, ENH: Add broadcast.ndim to match code elsewhere.
-- `#7757 <https://github.com/numpy/numpy/pull/7757>`__: Update 7175, BUG: Invalid read of size 4 in PyArray_FromFile
-- `#7759 <https://github.com/numpy/numpy/pull/7759>`__: BUG: Fix numpy.i support for numpy API < 1.7.
-- `#7760 <https://github.com/numpy/numpy/pull/7760>`__: ENH: Make assert_almost_equal & assert_array_almost_equal consistent.
-- `#7766 <https://github.com/numpy/numpy/pull/7766>`__: fix an English typo
-- `#7771 <https://github.com/numpy/numpy/pull/7771>`__: DOC: link geomspace from logspace
-- `#7773 <https://github.com/numpy/numpy/pull/7773>`__: DOC: Remove a redundant the
-- `#7777 <https://github.com/numpy/numpy/pull/7777>`__: DOC: Update Numpy 1.11.1 release notes.
-- `#7785 <https://github.com/numpy/numpy/pull/7785>`__: DOC: update wheel building procedure for release
-- `#7789 <https://github.com/numpy/numpy/pull/7789>`__: MRG: add note of 64-bit wheels on Windows
-- `#7791 <https://github.com/numpy/numpy/pull/7791>`__: f2py.compile issues (#7683)
-- `#7799 <https://github.com/numpy/numpy/pull/7799>`__: "lambda" is not allowed to use as keyword arguments in a sample...
-- `#7803 <https://github.com/numpy/numpy/pull/7803>`__: BUG: interpret 'c' PEP3118/struct type as 'S1'.
-- `#7807 <https://github.com/numpy/numpy/pull/7807>`__: DOC: Misplaced parens in formula
-- `#7817 <https://github.com/numpy/numpy/pull/7817>`__: BUG: Make sure npy_mul_with_overflow_<type> detects overflow.
-- `#7818 <https://github.com/numpy/numpy/pull/7818>`__: numpy/distutils/misc_util.py fix for #7809: check that _tmpdirs...
-- `#7820 <https://github.com/numpy/numpy/pull/7820>`__: MAINT: Allocate fewer bytes for empty arrays.
-- `#7823 <https://github.com/numpy/numpy/pull/7823>`__: BUG: Fixed masked array behavior for scalar inputs to np.ma.atleast_*d
-- `#7834 <https://github.com/numpy/numpy/pull/7834>`__: DOC: Added an example
-- `#7839 <https://github.com/numpy/numpy/pull/7839>`__: Pypy fixes
-- `#7840 <https://github.com/numpy/numpy/pull/7840>`__: Fix ATLAS version detection
-- `#7842 <https://github.com/numpy/numpy/pull/7842>`__: Fix versionadded tags
-- `#7848 <https://github.com/numpy/numpy/pull/7848>`__: MAINT: Fix remaining uses of deprecated Python imp module.
-- `#7853 <https://github.com/numpy/numpy/pull/7853>`__: BUG: Make sure numpy globals keep identity after reload.
-- `#7863 <https://github.com/numpy/numpy/pull/7863>`__: ENH: turn quicksort into introsort
-- `#7866 <https://github.com/numpy/numpy/pull/7866>`__: Document runtests extra argv
-- `#7871 <https://github.com/numpy/numpy/pull/7871>`__: BUG: handle introsort depth limit properly
-- `#7879 <https://github.com/numpy/numpy/pull/7879>`__: DOC: fix typo in documentation of loadtxt (closes #7878)
-- `#7885 <https://github.com/numpy/numpy/pull/7885>`__: Handle NetBSD specific <sys/endian.h>
-- `#7889 <https://github.com/numpy/numpy/pull/7889>`__: DOC: #7881. Fix link to record arrays
-- `#7894 <https://github.com/numpy/numpy/pull/7894>`__: fixup-7790, BUG: construct ma.array from np.array which contains...
-- `#7898 <https://github.com/numpy/numpy/pull/7898>`__: Spelling and grammar fix.
-- `#7903 <https://github.com/numpy/numpy/pull/7903>`__: BUG: fix float16 type not being called due to wrong ordering
-- `#7908 <https://github.com/numpy/numpy/pull/7908>`__: BLD: Fixed detection for recent MKL versions
-- `#7911 <https://github.com/numpy/numpy/pull/7911>`__: BUG: fix for issue#7835 (ma.median of 1d)
-- `#7912 <https://github.com/numpy/numpy/pull/7912>`__: ENH: skip or avoid gc/objectmodel differences btwn pypy and cpython
-- `#7918 <https://github.com/numpy/numpy/pull/7918>`__: ENH: allow numpy.apply_along_axis() to work with ndarray subclasses
-- `#7922 <https://github.com/numpy/numpy/pull/7922>`__: ENH: Add ma.convolve and ma.correlate for #6458
-- `#7925 <https://github.com/numpy/numpy/pull/7925>`__: Monkey-patch _msvccompile.gen_lib_option like any other compilators
-- `#7931 <https://github.com/numpy/numpy/pull/7931>`__: BUG: Check for HAVE_LDOUBLE_DOUBLE_DOUBLE_LE in npy_math_complex.
-- `#7936 <https://github.com/numpy/numpy/pull/7936>`__: ENH: improve duck typing inside iscomplexobj
-- `#7937 <https://github.com/numpy/numpy/pull/7937>`__: BUG: Guard against buggy comparisons in generic quicksort.
-- `#7938 <https://github.com/numpy/numpy/pull/7938>`__: DOC: add cbrt to math summary page
-- `#7941 <https://github.com/numpy/numpy/pull/7941>`__: BUG: Make sure numpy globals keep identity after reload.
-- `#7943 <https://github.com/numpy/numpy/pull/7943>`__: DOC: #7927. Remove deprecated note for memmap relevant for Python...
-- `#7952 <https://github.com/numpy/numpy/pull/7952>`__: BUG: Use keyword arguments to initialize Extension base class.
-- `#7956 <https://github.com/numpy/numpy/pull/7956>`__: BLD: remove __NUMPY_SETUP__ from builtins at end of setup.py
-- `#7963 <https://github.com/numpy/numpy/pull/7963>`__: BUG: MSVCCompiler grows 'lib' & 'include' env strings exponentially.
-- `#7965 <https://github.com/numpy/numpy/pull/7965>`__: BUG: cannot modify tuple after use
-- `#7976 <https://github.com/numpy/numpy/pull/7976>`__: DOC: Fixed documented dimension of return value
-- `#7977 <https://github.com/numpy/numpy/pull/7977>`__: DOC: Create 1.11.2 release notes.
-- `#7979 <https://github.com/numpy/numpy/pull/7979>`__: DOC: Corrected allowed keywords in add_(installed_)library
-- `#7980 <https://github.com/numpy/numpy/pull/7980>`__: ENH: Add ability to runtime select ufunc loops, add AVX2 integer...
-- `#7985 <https://github.com/numpy/numpy/pull/7985>`__: Rebase 7763, ENH: Add new warning suppression/filtering context
-- `#7987 <https://github.com/numpy/numpy/pull/7987>`__: DOC: See also np.load and np.memmap in np.lib.format.open_memmap
-- `#7988 <https://github.com/numpy/numpy/pull/7988>`__: DOC: Include docstring for cbrt, spacing and fabs in documentation
-- `#7999 <https://github.com/numpy/numpy/pull/7999>`__: ENH: add inplace cases to fast ufunc loop macros
-- `#8006 <https://github.com/numpy/numpy/pull/8006>`__: DOC: Update 1.11.2 release notes.
-- `#8008 <https://github.com/numpy/numpy/pull/8008>`__: MAINT: Remove leftover imp module imports.
-- `#8009 <https://github.com/numpy/numpy/pull/8009>`__: DOC: Fixed three typos in the c-info.ufunc-tutorial
-- `#8011 <https://github.com/numpy/numpy/pull/8011>`__: DOC: Update 1.11.2 release notes.
-- `#8014 <https://github.com/numpy/numpy/pull/8014>`__: BUG: Fix fid.close() to use os.close(fid)
-- `#8016 <https://github.com/numpy/numpy/pull/8016>`__: BUG: Fix numpy.ma.median.
-- `#8018 <https://github.com/numpy/numpy/pull/8018>`__: BUG: Fixes return for np.ma.count if keepdims is True and axis...
-- `#8021 <https://github.com/numpy/numpy/pull/8021>`__: DOC: change all non-code instances of Numpy to NumPy
-- `#8027 <https://github.com/numpy/numpy/pull/8027>`__: ENH: Add platform indepedent lib dir to PYTHONPATH
-- `#8028 <https://github.com/numpy/numpy/pull/8028>`__: DOC: Update 1.11.2 release notes.
-- `#8030 <https://github.com/numpy/numpy/pull/8030>`__: BUG: fix np.ma.median with only one non-masked value and an axis...
-- `#8038 <https://github.com/numpy/numpy/pull/8038>`__: MAINT: Update error message in rollaxis.
-- `#8040 <https://github.com/numpy/numpy/pull/8040>`__: Update add_newdocs.py
-- `#8042 <https://github.com/numpy/numpy/pull/8042>`__: BUG: core: fix bug in NpyIter buffering with discontinuous arrays
-- `#8045 <https://github.com/numpy/numpy/pull/8045>`__: DOC: Update 1.11.2 release notes.
-- `#8050 <https://github.com/numpy/numpy/pull/8050>`__: remove refcount semantics, now a.resize() almost always requires...
-- `#8051 <https://github.com/numpy/numpy/pull/8051>`__: Clear signaling NaN exceptions
-- `#8054 <https://github.com/numpy/numpy/pull/8054>`__: ENH: add signature argument to vectorize for vectorizing like...
-- `#8057 <https://github.com/numpy/numpy/pull/8057>`__: BUG: lib: Simplify (and fix) pad's handling of the pad_width
-- `#8061 <https://github.com/numpy/numpy/pull/8061>`__: BUG : financial.pmt modifies input (issue #8055)
-- `#8064 <https://github.com/numpy/numpy/pull/8064>`__: MAINT: Add PMIP files to .gitignore
-- `#8065 <https://github.com/numpy/numpy/pull/8065>`__: BUG: Assert fromfile ending earlier in pyx_processing
-- `#8066 <https://github.com/numpy/numpy/pull/8066>`__: BUG, TST: Fix python3-dbg bug in Travis script
-- `#8071 <https://github.com/numpy/numpy/pull/8071>`__: MAINT: Add Tempita to randint helpers
-- `#8075 <https://github.com/numpy/numpy/pull/8075>`__: DOC: Fix description of isinf in nan_to_num
-- `#8080 <https://github.com/numpy/numpy/pull/8080>`__: BUG: non-integers can end up in dtype offsets
-- `#8081 <https://github.com/numpy/numpy/pull/8081>`__: Update outdated Nose URL to nose.readthedocs.io
-- `#8083 <https://github.com/numpy/numpy/pull/8083>`__: ENH: Deprecation warnings for `/` integer division when running...
-- `#8084 <https://github.com/numpy/numpy/pull/8084>`__: DOC: Fix erroneous return type description for np.roots.
-- `#8087 <https://github.com/numpy/numpy/pull/8087>`__: BUG: financial.pmt modifies input #8055
-- `#8088 <https://github.com/numpy/numpy/pull/8088>`__: MAINT: Remove duplicate randint helpers code.
-- `#8093 <https://github.com/numpy/numpy/pull/8093>`__: MAINT: fix assert_raises_regex when used as a context manager
-- `#8096 <https://github.com/numpy/numpy/pull/8096>`__: ENH: Vendorize tempita.
-- `#8098 <https://github.com/numpy/numpy/pull/8098>`__: DOC: Enhance description/usage for np.linalg.eig*h
-- `#8103 <https://github.com/numpy/numpy/pull/8103>`__: Pypy fixes
-- `#8104 <https://github.com/numpy/numpy/pull/8104>`__: Fix test code on cpuinfo's main function
-- `#8107 <https://github.com/numpy/numpy/pull/8107>`__: BUG: Fix array printing with precision=0.
-- `#8109 <https://github.com/numpy/numpy/pull/8109>`__: Fix bug in ravel_multi_index for big indices (Issue #7546)
-- `#8110 <https://github.com/numpy/numpy/pull/8110>`__: BUG: distutils: fix issue with rpath in fcompiler/gnu.py
-- `#8111 <https://github.com/numpy/numpy/pull/8111>`__: ENH: Add a tool for release authors and PRs.
-- `#8112 <https://github.com/numpy/numpy/pull/8112>`__: DOC: Fix "See also" links in linalg.
-- `#8114 <https://github.com/numpy/numpy/pull/8114>`__: BUG: core: add missing error check after PyLong_AsSsize_t
-- `#8121 <https://github.com/numpy/numpy/pull/8121>`__: DOC: Improve histogram2d() example.
-- `#8122 <https://github.com/numpy/numpy/pull/8122>`__: BUG: Fix broken pickle in MaskedArray when dtype is object (Return...
-- `#8124 <https://github.com/numpy/numpy/pull/8124>`__: BUG: Fixed build break
-- `#8125 <https://github.com/numpy/numpy/pull/8125>`__: Rebase, BUG: Fixed deepcopy of F-order object arrays.
-- `#8127 <https://github.com/numpy/numpy/pull/8127>`__: BUG: integers to a negative integer powers should error.
-- `#8141 <https://github.com/numpy/numpy/pull/8141>`__: improve configure checks for broken systems
-- `#8142 <https://github.com/numpy/numpy/pull/8142>`__: BUG: np.ma.mean and var should return scalar if no mask
-- `#8148 <https://github.com/numpy/numpy/pull/8148>`__: BUG: import full module path in npy_load_module
-- `#8153 <https://github.com/numpy/numpy/pull/8153>`__: MAINT: Expose void-scalar "base" attribute in python
-- `#8156 <https://github.com/numpy/numpy/pull/8156>`__: DOC: added example with empty indices for a scalar, #8138
-- `#8160 <https://github.com/numpy/numpy/pull/8160>`__: BUG: fix _array2string for structured array (issue #5692)
-- `#8164 <https://github.com/numpy/numpy/pull/8164>`__: MAINT: Update mailmap for NumPy 1.12.0
-- `#8165 <https://github.com/numpy/numpy/pull/8165>`__: Fixup 8152, BUG: assert_allclose(..., equal_nan=False) doesn't...
-- `#8167 <https://github.com/numpy/numpy/pull/8167>`__: Fixup 8146, DOC: Clarify when PyArray_{Max, Min, Ptp} return...
-- `#8168 <https://github.com/numpy/numpy/pull/8168>`__: DOC: Minor spelling fix in genfromtxt() docstring.
-- `#8173 <https://github.com/numpy/numpy/pull/8173>`__: BLD: Enable build on AIX
-- `#8174 <https://github.com/numpy/numpy/pull/8174>`__: DOC: warn that dtype.descr is only for use in PEP3118
-- `#8177 <https://github.com/numpy/numpy/pull/8177>`__: MAINT: Add python 3.6 support to suppress_warnings
-- `#8178 <https://github.com/numpy/numpy/pull/8178>`__: MAINT: Fix ResourceWarning new in Python 3.6.
-- `#8180 <https://github.com/numpy/numpy/pull/8180>`__: FIX: protect stolen ref by PyArray_NewFromDescr in array_empty
-- `#8181 <https://github.com/numpy/numpy/pull/8181>`__: ENH: Improve announce to find github squash-merge commits.
-- `#8182 <https://github.com/numpy/numpy/pull/8182>`__: MAINT: Update .mailmap
-- `#8183 <https://github.com/numpy/numpy/pull/8183>`__: MAINT: Ediff1d performance
-- `#8184 <https://github.com/numpy/numpy/pull/8184>`__: MAINT: make `assert_allclose` behavior on `nan`s match pre 1.12
-- `#8188 <https://github.com/numpy/numpy/pull/8188>`__: DOC: 'highest' is exclusive for randint()
-- `#8189 <https://github.com/numpy/numpy/pull/8189>`__: BUG: setfield should raise if arr is not writeable
-- `#8190 <https://github.com/numpy/numpy/pull/8190>`__: ENH: Add a float_power function with at least float64 precision.
-- `#8197 <https://github.com/numpy/numpy/pull/8197>`__: DOC: Add missing arguments to np.ufunc.outer
-- `#8198 <https://github.com/numpy/numpy/pull/8198>`__: DEP: Deprecate the keepdims argument to accumulate
-- `#8199 <https://github.com/numpy/numpy/pull/8199>`__: MAINT: change path to env in distutils.system_info. Closes gh-8195.
-- `#8200 <https://github.com/numpy/numpy/pull/8200>`__: BUG: Fix structured array format functions
-- `#8202 <https://github.com/numpy/numpy/pull/8202>`__: ENH: specialize name of dev package by interpreter
-- `#8205 <https://github.com/numpy/numpy/pull/8205>`__: DOC: change development instructions from SSH to HTTPS access.
-- `#8216 <https://github.com/numpy/numpy/pull/8216>`__: DOC: Patch doc errors for atleast_nd and frombuffer
-- `#8218 <https://github.com/numpy/numpy/pull/8218>`__: BUG: ediff1d should return subclasses
-- `#8219 <https://github.com/numpy/numpy/pull/8219>`__: DOC: Turn SciPy references into links.
-- `#8222 <https://github.com/numpy/numpy/pull/8222>`__: ENH: Make numpy.mean() do more precise computation
-- `#8227 <https://github.com/numpy/numpy/pull/8227>`__: BUG: Better check for invalid bounds in np.random.uniform.
-- `#8231 <https://github.com/numpy/numpy/pull/8231>`__: ENH: Refactor numpy ** operators for numpy scalar integer powers
-- `#8234 <https://github.com/numpy/numpy/pull/8234>`__: DOC: Clarified when a copy is made in numpy.asarray
-- `#8236 <https://github.com/numpy/numpy/pull/8236>`__: DOC: Fix documentation pull requests.
-- `#8238 <https://github.com/numpy/numpy/pull/8238>`__: MAINT: Update pavement.py
-- `#8239 <https://github.com/numpy/numpy/pull/8239>`__: ENH: Improve announce tool.
-- `#8240 <https://github.com/numpy/numpy/pull/8240>`__: REL: Prepare for 1.12.x branch
-- `#8243 <https://github.com/numpy/numpy/pull/8243>`__: BUG: Update operator `**` tests for new behavior.
-- `#8246 <https://github.com/numpy/numpy/pull/8246>`__: REL: Reset strides for RELAXED_STRIDE_CHECKING for 1.12 releases.
-- `#8265 <https://github.com/numpy/numpy/pull/8265>`__: BUG: np.piecewise not working for scalars
-- `#8272 <https://github.com/numpy/numpy/pull/8272>`__: TST: Path test should resolve symlinks when comparing
-- `#8282 <https://github.com/numpy/numpy/pull/8282>`__: DOC: Update 1.12.0 release notes.
-- `#8286 <https://github.com/numpy/numpy/pull/8286>`__: BUG: Fix pavement.py write_release_task.
-- `#8296 <https://github.com/numpy/numpy/pull/8296>`__: BUG: Fix iteration over reversed subspaces in mapiter_@name@.
-- `#8304 <https://github.com/numpy/numpy/pull/8304>`__: BUG: Fix PyPy crash in PyUFunc_GenericReduction.
-- `#8319 <https://github.com/numpy/numpy/pull/8319>`__: BLD: blacklist powl (longdouble power function) on OS X.
-- `#8320 <https://github.com/numpy/numpy/pull/8320>`__: BUG: do not link to Accelerate if OpenBLAS, MKL or BLIS are found.
-- `#8322 <https://github.com/numpy/numpy/pull/8322>`__: BUG: fixed kind specifications for parameters
-- `#8336 <https://github.com/numpy/numpy/pull/8336>`__: BUG: fix packbits and unpackbits to correctly handle empty arrays
-- `#8338 <https://github.com/numpy/numpy/pull/8338>`__: BUG: fix test_api test that fails intermittently in python 3
-- `#8339 <https://github.com/numpy/numpy/pull/8339>`__: BUG: Fix ndarray.tofile large file corruption in append mode.
-- `#8359 <https://github.com/numpy/numpy/pull/8359>`__: BUG: Fix suppress_warnings (again) for Python 3.6.
-- `#8372 <https://github.com/numpy/numpy/pull/8372>`__: BUG: Fixes for ma.median and nanpercentile.
-- `#8373 <https://github.com/numpy/numpy/pull/8373>`__: BUG: correct letter case
-- `#8379 <https://github.com/numpy/numpy/pull/8379>`__: DOC: Update 1.12.0-notes.rst.
-- `#8390 <https://github.com/numpy/numpy/pull/8390>`__: ENH: retune apply_along_axis nanmedian cutoff in 1.12
-- `#8391 <https://github.com/numpy/numpy/pull/8391>`__: DEP: Fix escaped string characters deprecated in Python 3.6.
-- `#8394 <https://github.com/numpy/numpy/pull/8394>`__: DOC: create 1.11.3 release notes.
-- `#8399 <https://github.com/numpy/numpy/pull/8399>`__: BUG: Fix author search in announce.py
+* Aditya Panchal +
+* Ales Erjavec +
+* Alex Griffing
+* Alexandr Shadchin +
+* Alistair Muldal
+* Allan Haldane
+* Amit Aronovitch +
+* Andrei Kucharavy +
+* Antony Lee
+* Antti Kaihola +
+* Arne de Laat +
+* Auke Wiggers +
+* AustereCuriosity +
+* Badhri Narayanan Krishnakumar +
+* Ben North +
+* Ben Rowland +
+* Bertrand Lefebvre
+* Boxiang Sun
+* CJ Carey
+* Charles Harris
+* Christoph Gohlke
+* Daniel Ching +
+* Daniel Rasmussen +
+* Daniel Smith +
+* David Schaich +
+* Denis Alevi +
+* Devin Jeanpierre +
+* Dmitry Odzerikho
+* Dongjoon Hyun +
+* Edward Richards +
+* Ekaterina Tuzova +
+* Emilien Kofman +
+* Endolith
+* Eren Sezener +
+* Eric Moore
+* Eric Quintero +
+* Eric Wieser +
+* Erik M. Bray
+* Frederic Bastien
+* Friedrich Dunne +
+* Gerrit Holl
+* Golnaz Irannejad +
+* Graham Markall +
+* Greg Knoll +
+* Greg Young
+* Gustavo Serra Scalet +
+* Ines Wichert +
+* Irvin Probst +
+* Jaime Fernandez
+* James Sanders +
+* Jan David Mol +
+* Jan Schlüter
+* Jeremy Tuloup +
+* John Kirkham
+* John Zwinck +
+* Jonathan Helmus
+* Joseph Fox-Rabinovitz
+* Josh Wilson +
+* Joshua Warner +
+* Julian Taylor
+* Ka Wo Chen +
+* Kamil Rytarowski +
+* Kelsey Jordahl +
+* Kevin Deldycke +
+* Khaled Ben Abdallah Okuda +
+* Lion Krischer +
+* Loïc Estève +
+* Luca Mussi +
+* Mads Ohm Larsen +
+* Manoj Kumar +
+* Mario Emmenlauer +
+* Marshall Bockrath-Vandegrift +
+* Marshall Ward +
+* Marten van Kerkwijk
+* Mathieu Lamarre +
+* Matthew Brett
+* Matthew Harrigan +
+* Matthias Geier
+* Matti Picus +
+* Meet Udeshi +
+* Michael Felt +
+* Michael Goerz +
+* Michael Martin +
+* Michael Seifert +
+* Mike Nolta +
+* Nathaniel Beaver +
+* Nathaniel J. Smith
+* Naveen Arunachalam +
+* Nick Papior
+* Nikola Forró +
+* Oleksandr Pavlyk +
+* Olivier Grisel
+* Oren Amsalem +
+* Pauli Virtanen
+* Pavel Potocek +
+* Pedro Lacerda +
+* Peter Creasey +
+* Phil Elson +
+* Philip Gura +
+* Phillip J. Wolfram +
+* Pierre de Buyl +
+* Raghav RV +
+* Ralf Gommers
+* Ray Donnelly +
+* Rehas Sachdeva
+* Rob Malouf +
+* Robert Kern
+* Samuel St-Jean
+* Sanchez Gonzalez Alvaro +
+* Saurabh Mehta +
+* Scott Sanderson +
+* Sebastian Berg
+* Shayan Pooya +
+* Shota Kawabuchi +
+* Simon Conseil
+* Simon Gibbons
+* Sorin Sbarnea +
+* Stefan van der Walt
+* Stephan Hoyer
+* Steven J Kern +
+* Stuart Archibald
+* Tadeu Manoel +
+* Takuya Akiba +
+* Thomas A Caswell
+* Tom Bird +
+* Tony Kelman +
+* Toshihiro Kamishima +
+* Valentin Valls +
+* Varun Nayyar
+* Victor Stinner +
+* Warren Weckesser
+* Wendell Smith
+* Wojtek Ruszczewski +
+* Xavier Abellan Ecija +
+* Yaroslav Halchenko
+* Yash Shah +
+* Yinon Ehrlich +
+* Yu Feng +
+* nevimov +
+
+Pull requests merged
+====================
+
+A total of 418 pull requests were merged for this release.
+
+* `#4073 <https://github.com/numpy/numpy/pull/4073>`__: BUG: change real output checking to test if all imaginary parts...
+* `#4619 <https://github.com/numpy/numpy/pull/4619>`__: BUG : np.sum silently drops keepdims for sub-classes of ndarray
+* `#5488 <https://github.com/numpy/numpy/pull/5488>`__: ENH: add `contract`: optimizing numpy's einsum expression
+* `#5706 <https://github.com/numpy/numpy/pull/5706>`__: ENH: make some masked array methods behave more like ndarray...
+* `#5822 <https://github.com/numpy/numpy/pull/5822>`__: Allow many distributions to have a scale of 0.
+* `#6054 <https://github.com/numpy/numpy/pull/6054>`__: WIP: MAINT: Add deprecation warning to views of multi-field indexes
+* `#6298 <https://github.com/numpy/numpy/pull/6298>`__: Check lower base limit in base_repr.
+* `#6430 <https://github.com/numpy/numpy/pull/6430>`__: Fix issues with zero-width string fields
+* `#6656 <https://github.com/numpy/numpy/pull/6656>`__: ENH: usecols now accepts an int when only one column has to be...
+* `#6660 <https://github.com/numpy/numpy/pull/6660>`__: Added pathlib support for several functions
+* `#6872 <https://github.com/numpy/numpy/pull/6872>`__: ENH: linear interpolation of complex values in lib.interp
+* `#6997 <https://github.com/numpy/numpy/pull/6997>`__: MAINT: Simplify mtrand.pyx helpers
+* `#7003 <https://github.com/numpy/numpy/pull/7003>`__: BUG: Fix string copying for np.place
+* `#7026 <https://github.com/numpy/numpy/pull/7026>`__: DOC: Clarify behavior in np.random.uniform
+* `#7055 <https://github.com/numpy/numpy/pull/7055>`__: BUG: One Element Array Inputs Return Scalars in np.random
+* `#7063 <https://github.com/numpy/numpy/pull/7063>`__: REL: Update master branch after 1.11.x branch has been made.
+* `#7073 <https://github.com/numpy/numpy/pull/7073>`__: DOC: Update the 1.11.0 release notes.
+* `#7076 <https://github.com/numpy/numpy/pull/7076>`__: MAINT: Update the git .mailmap file.
+* `#7082 <https://github.com/numpy/numpy/pull/7082>`__: TST, DOC: Added Broadcasting Tests in test_random.py
+* `#7087 <https://github.com/numpy/numpy/pull/7087>`__: BLD: fix compilation on non glibc-Linuxes
+* `#7088 <https://github.com/numpy/numpy/pull/7088>`__: BUG: Have `norm` cast non-floating point arrays to 64-bit float...
+* `#7090 <https://github.com/numpy/numpy/pull/7090>`__: ENH: Added 'doane' and 'sqrt' estimators to np.histogram in numpy.function_base
+* `#7091 <https://github.com/numpy/numpy/pull/7091>`__: Revert "BLD: fix compilation on non glibc-Linuxes"
+* `#7092 <https://github.com/numpy/numpy/pull/7092>`__: BLD: fix compilation on non glibc-Linuxes
+* `#7099 <https://github.com/numpy/numpy/pull/7099>`__: TST: Suppressed warnings
+* `#7102 <https://github.com/numpy/numpy/pull/7102>`__: MAINT: Removed conditionals that are always false in datetime_strings.c
+* `#7105 <https://github.com/numpy/numpy/pull/7105>`__: DEP: Deprecate as_strided returning a writable array as default
+* `#7109 <https://github.com/numpy/numpy/pull/7109>`__: DOC: update Python versions requirements in the install docs
+* `#7114 <https://github.com/numpy/numpy/pull/7114>`__: MAINT: Fix typos in docs
+* `#7116 <https://github.com/numpy/numpy/pull/7116>`__: TST: Fixed f2py test for win32 virtualenv
+* `#7118 <https://github.com/numpy/numpy/pull/7118>`__: TST: Fixed f2py test for non-versioned python executables
+* `#7119 <https://github.com/numpy/numpy/pull/7119>`__: BUG: Fixed mingw.lib error
+* `#7125 <https://github.com/numpy/numpy/pull/7125>`__: DOC: Updated documentation wording and examples for np.percentile.
+* `#7129 <https://github.com/numpy/numpy/pull/7129>`__: BUG: Fixed 'midpoint' interpolation of np.percentile in odd cases.
+* `#7131 <https://github.com/numpy/numpy/pull/7131>`__: Fix setuptools sdist
+* `#7133 <https://github.com/numpy/numpy/pull/7133>`__: ENH: savez: temporary file alongside with target file and improve...
+* `#7134 <https://github.com/numpy/numpy/pull/7134>`__: MAINT: Fix some typos in a code string and comments
+* `#7141 <https://github.com/numpy/numpy/pull/7141>`__: BUG: Unpickled void scalars should be contiguous
+* `#7144 <https://github.com/numpy/numpy/pull/7144>`__: MAINT: Change `call_fortran` into `callfortran` in comments.
+* `#7145 <https://github.com/numpy/numpy/pull/7145>`__: BUG: Fixed regressions in np.piecewise in ref to #5737 and #5729.
+* `#7147 <https://github.com/numpy/numpy/pull/7147>`__: Temporarily disable __numpy_ufunc__
+* `#7148 <https://github.com/numpy/numpy/pull/7148>`__: ENH,TST: Bump stacklevel and add tests for warnings
+* `#7149 <https://github.com/numpy/numpy/pull/7149>`__: TST: Add missing suffix to temppath manager
+* `#7152 <https://github.com/numpy/numpy/pull/7152>`__: BUG: mode kwargs passed as unicode to np.pad raises an exception
+* `#7156 <https://github.com/numpy/numpy/pull/7156>`__: BUG: Reascertain that linspace respects ndarray subclasses in...
+* `#7167 <https://github.com/numpy/numpy/pull/7167>`__: DOC: Update Wikipedia references for mtrand.pyx
+* `#7171 <https://github.com/numpy/numpy/pull/7171>`__: TST: Fixed f2py test for Anaconda non-win32
+* `#7174 <https://github.com/numpy/numpy/pull/7174>`__: DOC: Fix broken pandas link in release notes
+* `#7177 <https://github.com/numpy/numpy/pull/7177>`__: ENH: added axis param for np.count_nonzero
+* `#7178 <https://github.com/numpy/numpy/pull/7178>`__: BUG: Fix binary_repr for negative numbers
+* `#7180 <https://github.com/numpy/numpy/pull/7180>`__: BUG: Fixed previous attempt to fix dimension mismatch in nanpercentile
+* `#7181 <https://github.com/numpy/numpy/pull/7181>`__: DOC: Updated minor typos in function_base.py and test_function_base.py
+* `#7191 <https://github.com/numpy/numpy/pull/7191>`__: DOC: add vstack, hstack, dstack reference to stack documentation.
+* `#7193 <https://github.com/numpy/numpy/pull/7193>`__: MAINT: Removed supurious assert in histogram estimators
+* `#7194 <https://github.com/numpy/numpy/pull/7194>`__: BUG: Raise a quieter `MaskedArrayFutureWarning` for mask changes.
+* `#7195 <https://github.com/numpy/numpy/pull/7195>`__: STY: Drop some trailing spaces in `numpy.ma.core`.
+* `#7196 <https://github.com/numpy/numpy/pull/7196>`__: Revert "DOC: add vstack, hstack, dstack reference to stack documentation."
+* `#7197 <https://github.com/numpy/numpy/pull/7197>`__: TST: Pin virtualenv used on Travis CI.
+* `#7198 <https://github.com/numpy/numpy/pull/7198>`__: ENH: Unlock the GIL for gufuncs
+* `#7199 <https://github.com/numpy/numpy/pull/7199>`__: MAINT: Cleanup for histogram bin estimator selection
+* `#7201 <https://github.com/numpy/numpy/pull/7201>`__: Raise IOError on not a file in python2
+* `#7202 <https://github.com/numpy/numpy/pull/7202>`__: MAINT: Made `iterable` return a boolean
+* `#7209 <https://github.com/numpy/numpy/pull/7209>`__: TST: Bump `virtualenv` to 14.0.6
+* `#7211 <https://github.com/numpy/numpy/pull/7211>`__: DOC: Fix fmin examples
+* `#7215 <https://github.com/numpy/numpy/pull/7215>`__: MAINT: Use PySlice_GetIndicesEx instead of custom reimplementation
+* `#7229 <https://github.com/numpy/numpy/pull/7229>`__: ENH: implement __complex__
+* `#7231 <https://github.com/numpy/numpy/pull/7231>`__: MRG: allow distributors to run custom init
+* `#7232 <https://github.com/numpy/numpy/pull/7232>`__: BLD: Switch order of test for lapack_mkl and openblas_lapack
+* `#7239 <https://github.com/numpy/numpy/pull/7239>`__: DOC: Removed residual merge markup from previous commit
+* `#7240 <https://github.com/numpy/numpy/pull/7240>`__: Change 'pubic' to 'public'.
+* `#7241 <https://github.com/numpy/numpy/pull/7241>`__: MAINT: update doc/sphinxext to numpydoc 0.6.0, and fix up some...
+* `#7243 <https://github.com/numpy/numpy/pull/7243>`__: ENH: Adding support to the range keyword for estimation of the...
+* `#7246 <https://github.com/numpy/numpy/pull/7246>`__: DOC: metion writeable keyword in as_strided in release notes
+* `#7247 <https://github.com/numpy/numpy/pull/7247>`__: TST: Fail quickly on AppVeyor for superseded PR builds
+* `#7248 <https://github.com/numpy/numpy/pull/7248>`__: DOC: remove link to documentation wiki editor from HOWTO_DOCUMENT.
+* `#7250 <https://github.com/numpy/numpy/pull/7250>`__: DOC,REL: Update 1.11.0 notes.
+* `#7251 <https://github.com/numpy/numpy/pull/7251>`__: BUG: only benchmark complex256 if it exists
+* `#7252 <https://github.com/numpy/numpy/pull/7252>`__: Forward port a fix and enhancement from 1.11.x
+* `#7253 <https://github.com/numpy/numpy/pull/7253>`__: DOC: note in h/v/dstack points users to stack/concatenate
+* `#7254 <https://github.com/numpy/numpy/pull/7254>`__: BUG: Enforce dtype for randint singletons
+* `#7256 <https://github.com/numpy/numpy/pull/7256>`__: MAINT: Use `is None` or `is not None` instead of `== None` or...
+* `#7257 <https://github.com/numpy/numpy/pull/7257>`__: DOC: Fix mismatched variable names in docstrings.
+* `#7258 <https://github.com/numpy/numpy/pull/7258>`__: ENH: Make numpy floor_divide and remainder agree with Python...
+* `#7260 <https://github.com/numpy/numpy/pull/7260>`__: BUG/TST: Fix #7259, do not "force scalar" for already scalar...
+* `#7261 <https://github.com/numpy/numpy/pull/7261>`__: Added self to mailmap
+* `#7266 <https://github.com/numpy/numpy/pull/7266>`__: BUG: Segfault for classes with deceptive __len__
+* `#7268 <https://github.com/numpy/numpy/pull/7268>`__: ENH: add geomspace function
+* `#7274 <https://github.com/numpy/numpy/pull/7274>`__: BUG: Preserve array order in np.delete
+* `#7275 <https://github.com/numpy/numpy/pull/7275>`__: DEP: Warn about assigning 'data' attribute of ndarray
+* `#7276 <https://github.com/numpy/numpy/pull/7276>`__: DOC: apply_along_axis missing whitespace inserted (before colon)
+* `#7278 <https://github.com/numpy/numpy/pull/7278>`__: BUG: Make returned unravel_index arrays writeable
+* `#7279 <https://github.com/numpy/numpy/pull/7279>`__: TST: Fixed elements being shuffled
+* `#7280 <https://github.com/numpy/numpy/pull/7280>`__: MAINT: Remove redundant trailing semicolons.
+* `#7285 <https://github.com/numpy/numpy/pull/7285>`__: BUG: Make Randint Backwards Compatible with Pandas
+* `#7286 <https://github.com/numpy/numpy/pull/7286>`__: MAINT: Fix typos in docs/comments of `ma` and `polynomial` modules.
+* `#7292 <https://github.com/numpy/numpy/pull/7292>`__: Clarify error on repr failure in assert_equal.
+* `#7294 <https://github.com/numpy/numpy/pull/7294>`__: ENH: add support for BLIS to numpy.distutils
+* `#7295 <https://github.com/numpy/numpy/pull/7295>`__: DOC: understanding code and getting started section to dev doc
+* `#7296 <https://github.com/numpy/numpy/pull/7296>`__: Revert part of #3907 which incorrectly propogated MaskedArray...
+* `#7299 <https://github.com/numpy/numpy/pull/7299>`__: DOC: Fix mismatched variable names in docstrings.
+* `#7300 <https://github.com/numpy/numpy/pull/7300>`__: DOC: dev: stop recommending keeping local master updated with...
+* `#7301 <https://github.com/numpy/numpy/pull/7301>`__: DOC: Update release notes
+* `#7305 <https://github.com/numpy/numpy/pull/7305>`__: BUG: Remove data race in mtrand: two threads could mutate the...
+* `#7307 <https://github.com/numpy/numpy/pull/7307>`__: DOC: Missing some characters in link.
+* `#7308 <https://github.com/numpy/numpy/pull/7308>`__: BUG: Incrementing the wrong reference on return
+* `#7310 <https://github.com/numpy/numpy/pull/7310>`__: STY: Fix GitHub rendering of ordered lists >9
+* `#7311 <https://github.com/numpy/numpy/pull/7311>`__: ENH: Make _pointer_type_cache functional
+* `#7313 <https://github.com/numpy/numpy/pull/7313>`__: DOC: corrected grammatical error in quickstart doc
+* `#7325 <https://github.com/numpy/numpy/pull/7325>`__: BUG, MAINT: Improve fromnumeric.py interface for downstream compatibility
+* `#7328 <https://github.com/numpy/numpy/pull/7328>`__: DEP: Deprecated using a float index in linspace
+* `#7331 <https://github.com/numpy/numpy/pull/7331>`__: Add comment, TST: fix MemoryError on win32
+* `#7332 <https://github.com/numpy/numpy/pull/7332>`__: Check for no solution in np.irr Fixes #6744
+* `#7338 <https://github.com/numpy/numpy/pull/7338>`__: TST: Install `pytz` in the CI.
+* `#7340 <https://github.com/numpy/numpy/pull/7340>`__: DOC: Fixed math rendering in tensordot docs.
+* `#7341 <https://github.com/numpy/numpy/pull/7341>`__: TST: Add test for #6469
+* `#7344 <https://github.com/numpy/numpy/pull/7344>`__: DOC: Fix more typos in docs and comments.
+* `#7346 <https://github.com/numpy/numpy/pull/7346>`__: Generalized flip
+* `#7347 <https://github.com/numpy/numpy/pull/7347>`__: ENH Generalized rot90
+* `#7348 <https://github.com/numpy/numpy/pull/7348>`__: Maint: Removed extra space from `ureduce`
+* `#7349 <https://github.com/numpy/numpy/pull/7349>`__: MAINT: Hide nan warnings for masked internal MA computations
+* `#7350 <https://github.com/numpy/numpy/pull/7350>`__: BUG: MA ufuncs should set mask to False, not array([False])
+* `#7351 <https://github.com/numpy/numpy/pull/7351>`__: TST: Fix some MA tests to avoid looking at the .data attribute
+* `#7358 <https://github.com/numpy/numpy/pull/7358>`__: BUG: pull request related to the issue #7353
+* `#7359 <https://github.com/numpy/numpy/pull/7359>`__: Update 7314, DOC: Clarify valid integer range for random.seed...
+* `#7361 <https://github.com/numpy/numpy/pull/7361>`__: MAINT: Fix copy and paste oversight.
+* `#7363 <https://github.com/numpy/numpy/pull/7363>`__: ENH: Make no unshare mask future warnings less noisy
+* `#7366 <https://github.com/numpy/numpy/pull/7366>`__: TST: fix #6542, add tests to check non-iterable argument raises...
+* `#7373 <https://github.com/numpy/numpy/pull/7373>`__: ENH: Add bitwise_and identity
+* `#7378 <https://github.com/numpy/numpy/pull/7378>`__: added NumPy logo and separator
+* `#7382 <https://github.com/numpy/numpy/pull/7382>`__: MAINT: cleanup np.average
+* `#7385 <https://github.com/numpy/numpy/pull/7385>`__: DOC: note about wheels / windows wheels for pypi
+* `#7386 <https://github.com/numpy/numpy/pull/7386>`__: Added label icon to Travis status
+* `#7397 <https://github.com/numpy/numpy/pull/7397>`__: BUG: incorrect type for objects whose __len__ fails
+* `#7398 <https://github.com/numpy/numpy/pull/7398>`__: DOC: fix typo
+* `#7404 <https://github.com/numpy/numpy/pull/7404>`__: Use PyMem_RawMalloc on Python 3.4 and newer
+* `#7406 <https://github.com/numpy/numpy/pull/7406>`__: ENH ufunc called on memmap return a ndarray
+* `#7407 <https://github.com/numpy/numpy/pull/7407>`__: BUG: Fix decref before incref for in-place accumulate
+* `#7410 <https://github.com/numpy/numpy/pull/7410>`__: DOC: add nanprod to the list of math routines
+* `#7414 <https://github.com/numpy/numpy/pull/7414>`__: Tweak corrcoef
+* `#7415 <https://github.com/numpy/numpy/pull/7415>`__: DOC: Documention fixes
+* `#7416 <https://github.com/numpy/numpy/pull/7416>`__: BUG: Incorrect handling of range in `histogram` with automatic...
+* `#7418 <https://github.com/numpy/numpy/pull/7418>`__: DOC: Minor typo fix, hermefik -> hermefit.
+* `#7421 <https://github.com/numpy/numpy/pull/7421>`__: ENH: adds np.nancumsum and np.nancumprod
+* `#7423 <https://github.com/numpy/numpy/pull/7423>`__: BUG: Ongoing fixes to PR#7416
+* `#7430 <https://github.com/numpy/numpy/pull/7430>`__: DOC: Update 1.11.0-notes.
+* `#7433 <https://github.com/numpy/numpy/pull/7433>`__: MAINT: FutureWarning for changes to np.average subclass handling
+* `#7437 <https://github.com/numpy/numpy/pull/7437>`__: np.full now defaults to the filling value's dtype.
+* `#7438 <https://github.com/numpy/numpy/pull/7438>`__: Allow rolling multiple axes at the same time.
+* `#7439 <https://github.com/numpy/numpy/pull/7439>`__: BUG: Do not try sequence repeat unless necessary
+* `#7442 <https://github.com/numpy/numpy/pull/7442>`__: MANT: Simplify diagonal length calculation logic
+* `#7445 <https://github.com/numpy/numpy/pull/7445>`__: BUG: reference count leak in bincount, fixes #6805
+* `#7446 <https://github.com/numpy/numpy/pull/7446>`__: DOC: ndarray typo fix
+* `#7447 <https://github.com/numpy/numpy/pull/7447>`__: BUG: scalar integer negative powers gave wrong results.
+* `#7448 <https://github.com/numpy/numpy/pull/7448>`__: DOC: array "See also" link to full and full_like instead of fill
+* `#7456 <https://github.com/numpy/numpy/pull/7456>`__: BUG: int overflow in reshape, fixes #7455, fixes #7293
+* `#7463 <https://github.com/numpy/numpy/pull/7463>`__: BUG: fix array too big error for wide dtypes.
+* `#7466 <https://github.com/numpy/numpy/pull/7466>`__: BUG: segfault inplace object reduceat, fixes #7465
+* `#7468 <https://github.com/numpy/numpy/pull/7468>`__: BUG: more on inplace reductions, fixes #615
+* `#7469 <https://github.com/numpy/numpy/pull/7469>`__: MAINT: Update git .mailmap
+* `#7472 <https://github.com/numpy/numpy/pull/7472>`__: MAINT: Update .mailmap.
+* `#7477 <https://github.com/numpy/numpy/pull/7477>`__: MAINT: Yet more .mailmap updates for recent contributors.
+* `#7481 <https://github.com/numpy/numpy/pull/7481>`__: BUG: Fix segfault in PyArray_OrderConverter
+* `#7482 <https://github.com/numpy/numpy/pull/7482>`__: BUG: Memory Leak in _GenericBinaryOutFunction
+* `#7489 <https://github.com/numpy/numpy/pull/7489>`__: Faster real_if_close.
+* `#7491 <https://github.com/numpy/numpy/pull/7491>`__: DOC: Update subclassing doc regarding downstream compatibility
+* `#7496 <https://github.com/numpy/numpy/pull/7496>`__: BUG: don't use pow for integer power ufunc loops.
+* `#7504 <https://github.com/numpy/numpy/pull/7504>`__: DOC: remove "arr" from keepdims docstrings
+* `#7505 <https://github.com/numpy/numpy/pull/7505>`__: MAIN: fix to #7382, make scl in np.average writeable
+* `#7507 <https://github.com/numpy/numpy/pull/7507>`__: MAINT: Remove nose.SkipTest import.
+* `#7508 <https://github.com/numpy/numpy/pull/7508>`__: DOC: link frompyfunc and vectorize
+* `#7511 <https://github.com/numpy/numpy/pull/7511>`__: numpy.power(0, 0) should return 1
+* `#7515 <https://github.com/numpy/numpy/pull/7515>`__: BUG: MaskedArray.count treats negative axes incorrectly
+* `#7518 <https://github.com/numpy/numpy/pull/7518>`__: BUG: Extend glibc complex trig functions blacklist to glibc <...
+* `#7521 <https://github.com/numpy/numpy/pull/7521>`__: DOC: rephrase writeup of memmap changes
+* `#7522 <https://github.com/numpy/numpy/pull/7522>`__: BUG: Fixed iteration over additional bad commands
+* `#7526 <https://github.com/numpy/numpy/pull/7526>`__: DOC: Removed an extra `:const:`
+* `#7529 <https://github.com/numpy/numpy/pull/7529>`__: BUG: Floating exception with invalid axis in np.lexsort
+* `#7534 <https://github.com/numpy/numpy/pull/7534>`__: MAINT: Update setup.py to reflect supported python versions.
+* `#7536 <https://github.com/numpy/numpy/pull/7536>`__: MAINT: Always use PyCapsule instead of PyCObject in mtrand.pyx
+* `#7539 <https://github.com/numpy/numpy/pull/7539>`__: MAINT: Cleanup of random stuff
+* `#7549 <https://github.com/numpy/numpy/pull/7549>`__: BUG: allow graceful recovery for no Liux compiler
+* `#7562 <https://github.com/numpy/numpy/pull/7562>`__: BUG: Fix test_from_object_array_unicode (test_defchararray.TestBasic)…
+* `#7565 <https://github.com/numpy/numpy/pull/7565>`__: BUG: Fix test_ctypeslib and test_indexing for debug interpreter
+* `#7566 <https://github.com/numpy/numpy/pull/7566>`__: MAINT: use manylinux1 wheel for cython
+* `#7568 <https://github.com/numpy/numpy/pull/7568>`__: Fix a false positive OverflowError in Python 3.x when value above...
+* `#7579 <https://github.com/numpy/numpy/pull/7579>`__: DOC: clarify purpose of Attributes section
+* `#7584 <https://github.com/numpy/numpy/pull/7584>`__: BUG: fixes #7572, percent in path
+* `#7586 <https://github.com/numpy/numpy/pull/7586>`__: Make np.ma.take works on scalars
+* `#7587 <https://github.com/numpy/numpy/pull/7587>`__: BUG: linalg.norm(): Don't convert object arrays to float
+* `#7598 <https://github.com/numpy/numpy/pull/7598>`__: Cast array size to int64 when loading from archive
+* `#7602 <https://github.com/numpy/numpy/pull/7602>`__: DOC: Remove isreal and iscomplex from ufunc list
+* `#7605 <https://github.com/numpy/numpy/pull/7605>`__: DOC: fix incorrect Gamma distribution parameterization comments
+* `#7609 <https://github.com/numpy/numpy/pull/7609>`__: BUG: Fix TypeError when raising TypeError
+* `#7611 <https://github.com/numpy/numpy/pull/7611>`__: ENH: expose test runner raise_warnings option
+* `#7614 <https://github.com/numpy/numpy/pull/7614>`__: BLD: Avoid using os.spawnve in favor of os.spawnv in exec_command
+* `#7618 <https://github.com/numpy/numpy/pull/7618>`__: BUG: distance arg of np.gradient must be scalar, fix docstring
+* `#7626 <https://github.com/numpy/numpy/pull/7626>`__: DOC: RST definition list fixes
+* `#7627 <https://github.com/numpy/numpy/pull/7627>`__: MAINT: unify tup processing, move tup use to after all PyTuple_SetItem...
+* `#7630 <https://github.com/numpy/numpy/pull/7630>`__: MAINT: add ifdef around PyDictProxy_Check macro
+* `#7631 <https://github.com/numpy/numpy/pull/7631>`__: MAINT: linalg: fix comment, simplify math
+* `#7634 <https://github.com/numpy/numpy/pull/7634>`__: BLD: correct C compiler customization in system_info.py Closes...
+* `#7635 <https://github.com/numpy/numpy/pull/7635>`__: BUG: ma.median alternate fix for #7592
+* `#7636 <https://github.com/numpy/numpy/pull/7636>`__: MAINT: clean up testing.assert_raises_regexp, 2.6-specific code...
+* `#7637 <https://github.com/numpy/numpy/pull/7637>`__: MAINT: clearer exception message when importing multiarray fails.
+* `#7639 <https://github.com/numpy/numpy/pull/7639>`__: TST: fix a set of test errors in master.
+* `#7643 <https://github.com/numpy/numpy/pull/7643>`__: DOC : minor changes to linspace docstring
+* `#7651 <https://github.com/numpy/numpy/pull/7651>`__: BUG: one to any power is still 1. Broken edgecase for int arrays
+* `#7655 <https://github.com/numpy/numpy/pull/7655>`__: BLD: Remove Intel compiler flag -xSSE4.2
+* `#7658 <https://github.com/numpy/numpy/pull/7658>`__: BUG: fix incorrect printing of 1D masked arrays
+* `#7659 <https://github.com/numpy/numpy/pull/7659>`__: BUG: Temporary fix for str(mvoid) for object field types
+* `#7664 <https://github.com/numpy/numpy/pull/7664>`__: BUG: Fix unicode with byte swap transfer and copyswap
+* `#7667 <https://github.com/numpy/numpy/pull/7667>`__: Restore histogram consistency
+* `#7668 <https://github.com/numpy/numpy/pull/7668>`__: ENH: Do not check the type of module.__dict__ explicit in test.
+* `#7669 <https://github.com/numpy/numpy/pull/7669>`__: BUG: boolean assignment no GIL release when transfer needs API
+* `#7673 <https://github.com/numpy/numpy/pull/7673>`__: DOC: Create Numpy 1.11.1 release notes.
+* `#7675 <https://github.com/numpy/numpy/pull/7675>`__: BUG: fix handling of right edge of final bin.
+* `#7678 <https://github.com/numpy/numpy/pull/7678>`__: BUG: Fix np.clip bug NaN handling for Visual Studio 2015
+* `#7679 <https://github.com/numpy/numpy/pull/7679>`__: MAINT: Fix up C++ comment in arraytypes.c.src.
+* `#7681 <https://github.com/numpy/numpy/pull/7681>`__: DOC: Update 1.11.1 release notes.
+* `#7686 <https://github.com/numpy/numpy/pull/7686>`__: ENH: Changing FFT cache to a bounded LRU cache
+* `#7688 <https://github.com/numpy/numpy/pull/7688>`__: DOC: fix broken genfromtxt examples in user guide. Closes gh-7662.
+* `#7689 <https://github.com/numpy/numpy/pull/7689>`__: BENCH: add correlate/convolve benchmarks.
+* `#7696 <https://github.com/numpy/numpy/pull/7696>`__: DOC: update wheel build / upload instructions
+* `#7699 <https://github.com/numpy/numpy/pull/7699>`__: BLD: preserve library order
+* `#7704 <https://github.com/numpy/numpy/pull/7704>`__: ENH: Add bits attribute to np.finfo
+* `#7712 <https://github.com/numpy/numpy/pull/7712>`__: BUG: Fix race condition with new FFT cache
+* `#7715 <https://github.com/numpy/numpy/pull/7715>`__: BUG: Remove memory leak in np.place
+* `#7719 <https://github.com/numpy/numpy/pull/7719>`__: BUG: Fix segfault in np.random.shuffle for arrays of different...
+* `#7723 <https://github.com/numpy/numpy/pull/7723>`__: Change mkl_info.dir_env_var from MKL to MKLROOT
+* `#7727 <https://github.com/numpy/numpy/pull/7727>`__: DOC: Corrections in Datetime Units-arrays.datetime.rst
+* `#7729 <https://github.com/numpy/numpy/pull/7729>`__: DOC: fix typo in savetxt docstring (closes #7620)
+* `#7733 <https://github.com/numpy/numpy/pull/7733>`__: Update 7525, DOC: Fix order='A' docs of np.array.
+* `#7734 <https://github.com/numpy/numpy/pull/7734>`__: Update 7542, ENH: Add `polyrootval` to numpy.polynomial
+* `#7735 <https://github.com/numpy/numpy/pull/7735>`__: BUG: fix issue on OS X with Python 3.x where npymath.ini was...
+* `#7739 <https://github.com/numpy/numpy/pull/7739>`__: DOC: Mention the changes of #6430 in the release notes.
+* `#7740 <https://github.com/numpy/numpy/pull/7740>`__: DOC: add reference to poisson rng
+* `#7743 <https://github.com/numpy/numpy/pull/7743>`__: Update 7476, DEP: deprecate Numeric-style typecodes, closes #2148
+* `#7744 <https://github.com/numpy/numpy/pull/7744>`__: DOC: Remove "ones_like" from ufuncs list (it is not)
+* `#7746 <https://github.com/numpy/numpy/pull/7746>`__: DOC: Clarify the effect of rcond in numpy.linalg.lstsq.
+* `#7747 <https://github.com/numpy/numpy/pull/7747>`__: Update 7672, BUG: Make sure we don't divide by zero
+* `#7748 <https://github.com/numpy/numpy/pull/7748>`__: DOC: Update float32 mean example in docstring
+* `#7754 <https://github.com/numpy/numpy/pull/7754>`__: Update 7612, ENH: Add broadcast.ndim to match code elsewhere.
+* `#7757 <https://github.com/numpy/numpy/pull/7757>`__: Update 7175, BUG: Invalid read of size 4 in PyArray_FromFile
+* `#7759 <https://github.com/numpy/numpy/pull/7759>`__: BUG: Fix numpy.i support for numpy API < 1.7.
+* `#7760 <https://github.com/numpy/numpy/pull/7760>`__: ENH: Make assert_almost_equal & assert_array_almost_equal consistent.
+* `#7766 <https://github.com/numpy/numpy/pull/7766>`__: fix an English typo
+* `#7771 <https://github.com/numpy/numpy/pull/7771>`__: DOC: link geomspace from logspace
+* `#7773 <https://github.com/numpy/numpy/pull/7773>`__: DOC: Remove a redundant the
+* `#7777 <https://github.com/numpy/numpy/pull/7777>`__: DOC: Update Numpy 1.11.1 release notes.
+* `#7785 <https://github.com/numpy/numpy/pull/7785>`__: DOC: update wheel building procedure for release
+* `#7789 <https://github.com/numpy/numpy/pull/7789>`__: MRG: add note of 64-bit wheels on Windows
+* `#7791 <https://github.com/numpy/numpy/pull/7791>`__: f2py.compile issues (#7683)
+* `#7799 <https://github.com/numpy/numpy/pull/7799>`__: "lambda" is not allowed to use as keyword arguments in a sample...
+* `#7803 <https://github.com/numpy/numpy/pull/7803>`__: BUG: interpret 'c' PEP3118/struct type as 'S1'.
+* `#7807 <https://github.com/numpy/numpy/pull/7807>`__: DOC: Misplaced parens in formula
+* `#7817 <https://github.com/numpy/numpy/pull/7817>`__: BUG: Make sure npy_mul_with_overflow_<type> detects overflow.
+* `#7818 <https://github.com/numpy/numpy/pull/7818>`__: numpy/distutils/misc_util.py fix for #7809: check that _tmpdirs...
+* `#7820 <https://github.com/numpy/numpy/pull/7820>`__: MAINT: Allocate fewer bytes for empty arrays.
+* `#7823 <https://github.com/numpy/numpy/pull/7823>`__: BUG: Fixed masked array behavior for scalar inputs to np.ma.atleast_*d
+* `#7834 <https://github.com/numpy/numpy/pull/7834>`__: DOC: Added an example
+* `#7839 <https://github.com/numpy/numpy/pull/7839>`__: Pypy fixes
+* `#7840 <https://github.com/numpy/numpy/pull/7840>`__: Fix ATLAS version detection
+* `#7842 <https://github.com/numpy/numpy/pull/7842>`__: Fix versionadded tags
+* `#7848 <https://github.com/numpy/numpy/pull/7848>`__: MAINT: Fix remaining uses of deprecated Python imp module.
+* `#7853 <https://github.com/numpy/numpy/pull/7853>`__: BUG: Make sure numpy globals keep identity after reload.
+* `#7863 <https://github.com/numpy/numpy/pull/7863>`__: ENH: turn quicksort into introsort
+* `#7866 <https://github.com/numpy/numpy/pull/7866>`__: Document runtests extra argv
+* `#7871 <https://github.com/numpy/numpy/pull/7871>`__: BUG: handle introsort depth limit properly
+* `#7879 <https://github.com/numpy/numpy/pull/7879>`__: DOC: fix typo in documentation of loadtxt (closes #7878)
+* `#7885 <https://github.com/numpy/numpy/pull/7885>`__: Handle NetBSD specific <sys/endian.h>
+* `#7889 <https://github.com/numpy/numpy/pull/7889>`__: DOC: #7881. Fix link to record arrays
+* `#7894 <https://github.com/numpy/numpy/pull/7894>`__: fixup-7790, BUG: construct ma.array from np.array which contains...
+* `#7898 <https://github.com/numpy/numpy/pull/7898>`__: Spelling and grammar fix.
+* `#7903 <https://github.com/numpy/numpy/pull/7903>`__: BUG: fix float16 type not being called due to wrong ordering
+* `#7908 <https://github.com/numpy/numpy/pull/7908>`__: BLD: Fixed detection for recent MKL versions
+* `#7911 <https://github.com/numpy/numpy/pull/7911>`__: BUG: fix for issue#7835 (ma.median of 1d)
+* `#7912 <https://github.com/numpy/numpy/pull/7912>`__: ENH: skip or avoid gc/objectmodel differences btwn pypy and cpython
+* `#7918 <https://github.com/numpy/numpy/pull/7918>`__: ENH: allow numpy.apply_along_axis() to work with ndarray subclasses
+* `#7922 <https://github.com/numpy/numpy/pull/7922>`__: ENH: Add ma.convolve and ma.correlate for #6458
+* `#7925 <https://github.com/numpy/numpy/pull/7925>`__: Monkey-patch _msvccompile.gen_lib_option like any other compilators
+* `#7931 <https://github.com/numpy/numpy/pull/7931>`__: BUG: Check for HAVE_LDOUBLE_DOUBLE_DOUBLE_LE in npy_math_complex.
+* `#7936 <https://github.com/numpy/numpy/pull/7936>`__: ENH: improve duck typing inside iscomplexobj
+* `#7937 <https://github.com/numpy/numpy/pull/7937>`__: BUG: Guard against buggy comparisons in generic quicksort.
+* `#7938 <https://github.com/numpy/numpy/pull/7938>`__: DOC: add cbrt to math summary page
+* `#7941 <https://github.com/numpy/numpy/pull/7941>`__: BUG: Make sure numpy globals keep identity after reload.
+* `#7943 <https://github.com/numpy/numpy/pull/7943>`__: DOC: #7927. Remove deprecated note for memmap relevant for Python...
+* `#7952 <https://github.com/numpy/numpy/pull/7952>`__: BUG: Use keyword arguments to initialize Extension base class.
+* `#7956 <https://github.com/numpy/numpy/pull/7956>`__: BLD: remove __NUMPY_SETUP__ from builtins at end of setup.py
+* `#7963 <https://github.com/numpy/numpy/pull/7963>`__: BUG: MSVCCompiler grows 'lib' & 'include' env strings exponentially.
+* `#7965 <https://github.com/numpy/numpy/pull/7965>`__: BUG: cannot modify tuple after use
+* `#7976 <https://github.com/numpy/numpy/pull/7976>`__: DOC: Fixed documented dimension of return value
+* `#7977 <https://github.com/numpy/numpy/pull/7977>`__: DOC: Create 1.11.2 release notes.
+* `#7979 <https://github.com/numpy/numpy/pull/7979>`__: DOC: Corrected allowed keywords in add_(installed_)library
+* `#7980 <https://github.com/numpy/numpy/pull/7980>`__: ENH: Add ability to runtime select ufunc loops, add AVX2 integer...
+* `#7985 <https://github.com/numpy/numpy/pull/7985>`__: Rebase 7763, ENH: Add new warning suppression/filtering context
+* `#7987 <https://github.com/numpy/numpy/pull/7987>`__: DOC: See also np.load and np.memmap in np.lib.format.open_memmap
+* `#7988 <https://github.com/numpy/numpy/pull/7988>`__: DOC: Include docstring for cbrt, spacing and fabs in documentation
+* `#7999 <https://github.com/numpy/numpy/pull/7999>`__: ENH: add inplace cases to fast ufunc loop macros
+* `#8006 <https://github.com/numpy/numpy/pull/8006>`__: DOC: Update 1.11.2 release notes.
+* `#8008 <https://github.com/numpy/numpy/pull/8008>`__: MAINT: Remove leftover imp module imports.
+* `#8009 <https://github.com/numpy/numpy/pull/8009>`__: DOC: Fixed three typos in the c-info.ufunc-tutorial
+* `#8011 <https://github.com/numpy/numpy/pull/8011>`__: DOC: Update 1.11.2 release notes.
+* `#8014 <https://github.com/numpy/numpy/pull/8014>`__: BUG: Fix fid.close() to use os.close(fid)
+* `#8016 <https://github.com/numpy/numpy/pull/8016>`__: BUG: Fix numpy.ma.median.
+* `#8018 <https://github.com/numpy/numpy/pull/8018>`__: BUG: Fixes return for np.ma.count if keepdims is True and axis...
+* `#8021 <https://github.com/numpy/numpy/pull/8021>`__: DOC: change all non-code instances of Numpy to NumPy
+* `#8027 <https://github.com/numpy/numpy/pull/8027>`__: ENH: Add platform indepedent lib dir to PYTHONPATH
+* `#8028 <https://github.com/numpy/numpy/pull/8028>`__: DOC: Update 1.11.2 release notes.
+* `#8030 <https://github.com/numpy/numpy/pull/8030>`__: BUG: fix np.ma.median with only one non-masked value and an axis...
+* `#8038 <https://github.com/numpy/numpy/pull/8038>`__: MAINT: Update error message in rollaxis.
+* `#8040 <https://github.com/numpy/numpy/pull/8040>`__: Update add_newdocs.py
+* `#8042 <https://github.com/numpy/numpy/pull/8042>`__: BUG: core: fix bug in NpyIter buffering with discontinuous arrays
+* `#8045 <https://github.com/numpy/numpy/pull/8045>`__: DOC: Update 1.11.2 release notes.
+* `#8050 <https://github.com/numpy/numpy/pull/8050>`__: remove refcount semantics, now a.resize() almost always requires...
+* `#8051 <https://github.com/numpy/numpy/pull/8051>`__: Clear signaling NaN exceptions
+* `#8054 <https://github.com/numpy/numpy/pull/8054>`__: ENH: add signature argument to vectorize for vectorizing like...
+* `#8057 <https://github.com/numpy/numpy/pull/8057>`__: BUG: lib: Simplify (and fix) pad's handling of the pad_width
+* `#8061 <https://github.com/numpy/numpy/pull/8061>`__: BUG : financial.pmt modifies input (issue #8055)
+* `#8064 <https://github.com/numpy/numpy/pull/8064>`__: MAINT: Add PMIP files to .gitignore
+* `#8065 <https://github.com/numpy/numpy/pull/8065>`__: BUG: Assert fromfile ending earlier in pyx_processing
+* `#8066 <https://github.com/numpy/numpy/pull/8066>`__: BUG, TST: Fix python3-dbg bug in Travis script
+* `#8071 <https://github.com/numpy/numpy/pull/8071>`__: MAINT: Add Tempita to randint helpers
+* `#8075 <https://github.com/numpy/numpy/pull/8075>`__: DOC: Fix description of isinf in nan_to_num
+* `#8080 <https://github.com/numpy/numpy/pull/8080>`__: BUG: non-integers can end up in dtype offsets
+* `#8081 <https://github.com/numpy/numpy/pull/8081>`__: Update outdated Nose URL to nose.readthedocs.io
+* `#8083 <https://github.com/numpy/numpy/pull/8083>`__: ENH: Deprecation warnings for `/` integer division when running...
+* `#8084 <https://github.com/numpy/numpy/pull/8084>`__: DOC: Fix erroneous return type description for np.roots.
+* `#8087 <https://github.com/numpy/numpy/pull/8087>`__: BUG: financial.pmt modifies input #8055
+* `#8088 <https://github.com/numpy/numpy/pull/8088>`__: MAINT: Remove duplicate randint helpers code.
+* `#8093 <https://github.com/numpy/numpy/pull/8093>`__: MAINT: fix assert_raises_regex when used as a context manager
+* `#8096 <https://github.com/numpy/numpy/pull/8096>`__: ENH: Vendorize tempita.
+* `#8098 <https://github.com/numpy/numpy/pull/8098>`__: DOC: Enhance description/usage for np.linalg.eig*h
+* `#8103 <https://github.com/numpy/numpy/pull/8103>`__: Pypy fixes
+* `#8104 <https://github.com/numpy/numpy/pull/8104>`__: Fix test code on cpuinfo's main function
+* `#8107 <https://github.com/numpy/numpy/pull/8107>`__: BUG: Fix array printing with precision=0.
+* `#8109 <https://github.com/numpy/numpy/pull/8109>`__: Fix bug in ravel_multi_index for big indices (Issue #7546)
+* `#8110 <https://github.com/numpy/numpy/pull/8110>`__: BUG: distutils: fix issue with rpath in fcompiler/gnu.py
+* `#8111 <https://github.com/numpy/numpy/pull/8111>`__: ENH: Add a tool for release authors and PRs.
+* `#8112 <https://github.com/numpy/numpy/pull/8112>`__: DOC: Fix "See also" links in linalg.
+* `#8114 <https://github.com/numpy/numpy/pull/8114>`__: BUG: core: add missing error check after PyLong_AsSsize_t
+* `#8121 <https://github.com/numpy/numpy/pull/8121>`__: DOC: Improve histogram2d() example.
+* `#8122 <https://github.com/numpy/numpy/pull/8122>`__: BUG: Fix broken pickle in MaskedArray when dtype is object (Return...
+* `#8124 <https://github.com/numpy/numpy/pull/8124>`__: BUG: Fixed build break
+* `#8125 <https://github.com/numpy/numpy/pull/8125>`__: Rebase, BUG: Fixed deepcopy of F-order object arrays.
+* `#8127 <https://github.com/numpy/numpy/pull/8127>`__: BUG: integers to a negative integer powers should error.
+* `#8141 <https://github.com/numpy/numpy/pull/8141>`__: improve configure checks for broken systems
+* `#8142 <https://github.com/numpy/numpy/pull/8142>`__: BUG: np.ma.mean and var should return scalar if no mask
+* `#8148 <https://github.com/numpy/numpy/pull/8148>`__: BUG: import full module path in npy_load_module
+* `#8153 <https://github.com/numpy/numpy/pull/8153>`__: MAINT: Expose void-scalar "base" attribute in python
+* `#8156 <https://github.com/numpy/numpy/pull/8156>`__: DOC: added example with empty indices for a scalar, #8138
+* `#8160 <https://github.com/numpy/numpy/pull/8160>`__: BUG: fix _array2string for structured array (issue #5692)
+* `#8164 <https://github.com/numpy/numpy/pull/8164>`__: MAINT: Update mailmap for NumPy 1.12.0
+* `#8165 <https://github.com/numpy/numpy/pull/8165>`__: Fixup 8152, BUG: assert_allclose(..., equal_nan=False) doesn't...
+* `#8167 <https://github.com/numpy/numpy/pull/8167>`__: Fixup 8146, DOC: Clarify when PyArray_{Max, Min, Ptp} return...
+* `#8168 <https://github.com/numpy/numpy/pull/8168>`__: DOC: Minor spelling fix in genfromtxt() docstring.
+* `#8173 <https://github.com/numpy/numpy/pull/8173>`__: BLD: Enable build on AIX
+* `#8174 <https://github.com/numpy/numpy/pull/8174>`__: DOC: warn that dtype.descr is only for use in PEP3118
+* `#8177 <https://github.com/numpy/numpy/pull/8177>`__: MAINT: Add python 3.6 support to suppress_warnings
+* `#8178 <https://github.com/numpy/numpy/pull/8178>`__: MAINT: Fix ResourceWarning new in Python 3.6.
+* `#8180 <https://github.com/numpy/numpy/pull/8180>`__: FIX: protect stolen ref by PyArray_NewFromDescr in array_empty
+* `#8181 <https://github.com/numpy/numpy/pull/8181>`__: ENH: Improve announce to find github squash-merge commits.
+* `#8182 <https://github.com/numpy/numpy/pull/8182>`__: MAINT: Update .mailmap
+* `#8183 <https://github.com/numpy/numpy/pull/8183>`__: MAINT: Ediff1d performance
+* `#8184 <https://github.com/numpy/numpy/pull/8184>`__: MAINT: make `assert_allclose` behavior on `nan`s match pre 1.12
+* `#8188 <https://github.com/numpy/numpy/pull/8188>`__: DOC: 'highest' is exclusive for randint()
+* `#8189 <https://github.com/numpy/numpy/pull/8189>`__: BUG: setfield should raise if arr is not writeable
+* `#8190 <https://github.com/numpy/numpy/pull/8190>`__: ENH: Add a float_power function with at least float64 precision.
+* `#8197 <https://github.com/numpy/numpy/pull/8197>`__: DOC: Add missing arguments to np.ufunc.outer
+* `#8198 <https://github.com/numpy/numpy/pull/8198>`__: DEP: Deprecate the keepdims argument to accumulate
+* `#8199 <https://github.com/numpy/numpy/pull/8199>`__: MAINT: change path to env in distutils.system_info. Closes gh-8195.
+* `#8200 <https://github.com/numpy/numpy/pull/8200>`__: BUG: Fix structured array format functions
+* `#8202 <https://github.com/numpy/numpy/pull/8202>`__: ENH: specialize name of dev package by interpreter
+* `#8205 <https://github.com/numpy/numpy/pull/8205>`__: DOC: change development instructions from SSH to HTTPS access.
+* `#8216 <https://github.com/numpy/numpy/pull/8216>`__: DOC: Patch doc errors for atleast_nd and frombuffer
+* `#8218 <https://github.com/numpy/numpy/pull/8218>`__: BUG: ediff1d should return subclasses
+* `#8219 <https://github.com/numpy/numpy/pull/8219>`__: DOC: Turn SciPy references into links.
+* `#8222 <https://github.com/numpy/numpy/pull/8222>`__: ENH: Make numpy.mean() do more precise computation
+* `#8227 <https://github.com/numpy/numpy/pull/8227>`__: BUG: Better check for invalid bounds in np.random.uniform.
+* `#8231 <https://github.com/numpy/numpy/pull/8231>`__: ENH: Refactor numpy ** operators for numpy scalar integer powers
+* `#8234 <https://github.com/numpy/numpy/pull/8234>`__: DOC: Clarified when a copy is made in numpy.asarray
+* `#8236 <https://github.com/numpy/numpy/pull/8236>`__: DOC: Fix documentation pull requests.
+* `#8238 <https://github.com/numpy/numpy/pull/8238>`__: MAINT: Update pavement.py
+* `#8239 <https://github.com/numpy/numpy/pull/8239>`__: ENH: Improve announce tool.
+* `#8240 <https://github.com/numpy/numpy/pull/8240>`__: REL: Prepare for 1.12.x branch
+* `#8243 <https://github.com/numpy/numpy/pull/8243>`__: BUG: Update operator `**` tests for new behavior.
+* `#8246 <https://github.com/numpy/numpy/pull/8246>`__: REL: Reset strides for RELAXED_STRIDE_CHECKING for 1.12 releases.
+* `#8265 <https://github.com/numpy/numpy/pull/8265>`__: BUG: np.piecewise not working for scalars
+* `#8272 <https://github.com/numpy/numpy/pull/8272>`__: TST: Path test should resolve symlinks when comparing
+* `#8282 <https://github.com/numpy/numpy/pull/8282>`__: DOC: Update 1.12.0 release notes.
+* `#8286 <https://github.com/numpy/numpy/pull/8286>`__: BUG: Fix pavement.py write_release_task.
+* `#8296 <https://github.com/numpy/numpy/pull/8296>`__: BUG: Fix iteration over reversed subspaces in mapiter_@name@.
+* `#8304 <https://github.com/numpy/numpy/pull/8304>`__: BUG: Fix PyPy crash in PyUFunc_GenericReduction.
+* `#8319 <https://github.com/numpy/numpy/pull/8319>`__: BLD: blacklist powl (longdouble power function) on OS X.
+* `#8320 <https://github.com/numpy/numpy/pull/8320>`__: BUG: do not link to Accelerate if OpenBLAS, MKL or BLIS are found.
+* `#8322 <https://github.com/numpy/numpy/pull/8322>`__: BUG: fixed kind specifications for parameters
+* `#8336 <https://github.com/numpy/numpy/pull/8336>`__: BUG: fix packbits and unpackbits to correctly handle empty arrays
+* `#8338 <https://github.com/numpy/numpy/pull/8338>`__: BUG: fix test_api test that fails intermittently in python 3
+* `#8339 <https://github.com/numpy/numpy/pull/8339>`__: BUG: Fix ndarray.tofile large file corruption in append mode.
+* `#8359 <https://github.com/numpy/numpy/pull/8359>`__: BUG: Fix suppress_warnings (again) for Python 3.6.
+* `#8372 <https://github.com/numpy/numpy/pull/8372>`__: BUG: Fixes for ma.median and nanpercentile.
+* `#8373 <https://github.com/numpy/numpy/pull/8373>`__: BUG: correct letter case
+* `#8379 <https://github.com/numpy/numpy/pull/8379>`__: DOC: Update 1.12.0-notes.rst.
+* `#8390 <https://github.com/numpy/numpy/pull/8390>`__: ENH: retune apply_along_axis nanmedian cutoff in 1.12
+* `#8391 <https://github.com/numpy/numpy/pull/8391>`__: DEP: Fix escaped string characters deprecated in Python 3.6.
+* `#8394 <https://github.com/numpy/numpy/pull/8394>`__: DOC: create 1.11.3 release notes.
+* `#8399 <https://github.com/numpy/numpy/pull/8399>`__: BUG: Fix author search in announce.py
+* `#8402 <https://github.com/numpy/numpy/pull/8402>`__: DOC, MAINT: Update 1.12.0 notes and mailmap.
+* `#8418 <https://github.com/numpy/numpy/pull/8418>`__: BUG: Fix ma.median even elements for 1.12
+* `#8424 <https://github.com/numpy/numpy/pull/8424>`__: DOC: Fix tools and release notes to be more markdown compatible.
+* `#8427 <https://github.com/numpy/numpy/pull/8427>`__: BUG: Add a lock to assert_equal and other testing functions
+* `#8431 <https://github.com/numpy/numpy/pull/8431>`__: BUG: Fix apply_along_axis() for when func1d() returns a non-ndarray.
+* `#8432 <https://github.com/numpy/numpy/pull/8432>`__: BUG: Let linspace accept input that has an array_interface.
+* `#8437 <https://github.com/numpy/numpy/pull/8437>`__: TST: Update 3.6-dev tests to 3.6 after Python final release.
+* `#8439 <https://github.com/numpy/numpy/pull/8439>`__: DOC: Update 1.12.0 release notes.
+* `#8466 <https://github.com/numpy/numpy/pull/8466>`__: MAINT: Update mailmap entries.
+* `#8467 <https://github.com/numpy/numpy/pull/8467>`__: DOC: Back-port the missing part of gh-8464.
+* `#8476 <https://github.com/numpy/numpy/pull/8476>`__: DOC: Update 1.12.0 release notes.
+* `#8477 <https://github.com/numpy/numpy/pull/8477>`__: DOC: Update 1.12.0 release notes.
diff --git a/doc/release/1.12.1-notes.rst b/doc/release/1.12.1-notes.rst
new file mode 100644
index 000000000..9e18a6fc7
--- /dev/null
+++ b/doc/release/1.12.1-notes.rst
@@ -0,0 +1,9 @@
+==========================
+NumPy 1.12.1 Release Notes
+==========================
+
+NumPy 1.12.1 supports Python 2.7 and 3.4 - 3.6 and fixes bugs and regressions
+found in NumPy 1.12.0. Wheels for Linux, Windows, and OSX can be found on pypi,
+
+Fixes Merged
+============
diff --git a/doc/release/1.13.0-notes.rst b/doc/release/1.13.0-notes.rst
index eed3f7266..3c22b1f61 100644
--- a/doc/release/1.13.0-notes.rst
+++ b/doc/release/1.13.0-notes.rst
@@ -56,6 +56,26 @@ See Changes section for more detail.
* ``array == None`` and ``array != None`` do element-wise comparison.
* ``np.equal, np.not_equal``, object identity doesn't override comparison result.
+dtypes are now always true
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Previously ``bool(dtype)`` would fall back to the default python
+implementation, which checked if ``len(dtype) > 0``. Since ``dtype`` objects
+implement ``__len__`` as the number of record fields, ``bool`` of scalar dtypes
+would evaluate to ``False``, which was unintuitive. Now ``bool(dtype) == True``
+for all dtypes.
+
+``__getslice__`` and ``__setslice__`` have been removed from ``ndarray``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When subclassing np.ndarray in Python 2.7, it is no longer _necessary_ to
+implement ``__*slice__`` on the derived class, as ``__*item__`` will intercept
+these calls correctly.
+
+Any code that did implement these will work exactly as before, with the
+obvious exception of any code that tries to directly call
+``ndarray.__getslice__`` (e.g. through ``super(...).__getslice__``). In
+this case, ``.__getitem__(slice(start, end))`` will act as a replacement.
+
C API
~~~~~
@@ -83,13 +103,89 @@ for instance). Note that this does not remove the need for Mingwpy; if you make
extensive use of the runtime, you will most likely run into issues_. Instead,
it should be regarded as a band-aid until Mingwpy is fully functional.
+Extensions can also be compiled using the MinGW toolset using the runtime
+library from the (moveable) WinPython 3.4 distribution, which can be useful for
+programs with a PySide1/Qt4 front-end.
+
.. _MinGW: https://sf.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/6.2.0/threads-win32/seh/
.. _issues: https://mingwpy.github.io/issues.html
+Performance improvements for ``packbits`` and ``unpackbits``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The functions ``numpy.packbits`` with boolean input and ``numpy.unpackbits`` have
+been optimized to be a significantly faster for contiguous data.
+
+Fix for PPC long double floating point information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In previous versions of numpy, the ``finfo`` function returned invalid
+information about the `double double`_ format of the ``longdouble`` float type
+on Power PC (PPC). The invalid values resulted from the failure of the numpy
+algorithm to deal with the `variable number of digits in the significand
+<https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/com.ibm.aix.genprogc/128bit_long_double_floating-point_datatype.htm>`_
+that are a feature of PPC long doubles. This release by-passes the failing
+algorithm by using heuristics to detect the presence of the PPC double double
+format. A side-effect of using these heuristics is that the ``finfo``
+function is faster than previous releases.
+
+.. _issues: https://github.com/numpy/numpy/issues/2669
+
+.. _double double: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic
+
+Support for returning arrays of arbitrary dimensionality in `apply_along_axis`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Previously, only scalars or 1D arrays could be returned by the function passed
+to `apply_along_axis`. Now, it can return an array of any dimensionality
+(including 0D), and the shape of this array replaces the axis of the array
+being iterated over.
+
+
Changes
=======
+Ufunc behavior for overlapping inputs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Operations where ufunc input and output operands have memory overlap
+produced undefined results in previous Numpy versions, due to data
+dependency issues. In Numpy 1.13.0, results from such operations are
+now defined to be the same as for equivalent operations where there is
+no memory overlap.
+
+Operations affected now make temporary copies, as needed to eliminate
+data dependency. As detecting these cases is computationally
+expensive, a heuristic is used, which may in rare cases result to
+needless temporary copies. For operations where the data dependency
+is simple enough for the heuristic to analyze, temporary copies will
+not be made even if the arrays overlap, if it can be deduced copies
+are not necessary. As an example,``np.add(a, b, out=a)`` will not
+involve copies.
+
+To illustrate a previously undefined operation
+
+>>> x = np.arange(16).astype(float)
+>>> np.add(x[1:], x[:-1], out=x[1:])
+
+In Numpy 1.13.0 the last line is guaranteed to be equivalent to
+
+>>> np.add(x[1:].copy(), x[:-1].copy(), out=x[1:])
+
+A similar operation with simple non-problematic data dependence is
+
+>>> x = np.arange(16).astype(float)
+>>> np.add(x[1:], x[:-1], out=x[:-1])
+
+It will continue to produce the same results as in previous Numpy
+versions, and will not involve unnecessary temporary copies.
+
+The change applies also to in-place binary operations, for example:
+
+>>> x = np.random.rand(500, 500)
+>>> x += x.T
+
+This statement is now guaranteed to be equivalent to ``x[...] = x + x.T``,
+whereas in previous Numpy versions the results were undefined.
+
``average`` now preserves subclasses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For ndarray subclasses, ``numpy.average`` will now return an instance of the
@@ -124,3 +220,29 @@ Boolean indexing changes
* Boolean indexing into scalar arrays return a new 1-d array. This means that
``array(1)[array(True)]`` gives ``array([1])`` and not the original array.
+``np.random.multivariate_normal`` behavior with bad covariance matrix
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is now possible to adjust the behavior the function will have when dealing
+with the covariance matrix by using two new keyword arguments:
+
+* ``tol`` can be used to specify a tolerance to use when checking that
+ the covariance matrix is positive semidefinite.
+
+* ``check_valid`` can be used to configure what the function will do in the
+ presence of a matrix that is not positive semidefinite. Valid options are
+ ``ignore``, ``warn`` and ``raise``. The default value, ``warn`` keeps the
+ the behavior used on previous releases.
+
+``assert_array_less`` compares ``np.inf`` and ``-np.inf`` now
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Previously, ``np.testing.assert_array_less`` ignored all infinite values. This
+is not the expected behavior both according to documentation and intuitively.
+Now, -inf < x < inf is considered ``True`` for any real number x and all
+other cases fail.
+
+``offset`` attribute value in ``memmap`` objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The ``offset`` attribute in a ``memmap`` object is now set to the
+offset into the file. This is a behaviour change only for offsets
+greater than ``mmap.ALLOCATIONGRANULARITY``.
diff --git a/doc/source/reference/arrays.indexing.rst b/doc/source/reference/arrays.indexing.rst
index b7bc3a655..6a5f428da 100644
--- a/doc/source/reference/arrays.indexing.rst
+++ b/doc/source/reference/arrays.indexing.rst
@@ -36,8 +36,8 @@ objects, the :const:`Ellipsis` object, or the :const:`newaxis` object,
but not for integer arrays or other embedded sequences.
.. index::
- triple: ndarray; special methods; getslice
- triple: ndarray; special methods; setslice
+ triple: ndarray; special methods; getitem
+ triple: ndarray; special methods; setitem
single: ellipsis
single: newaxis
diff --git a/doc/source/reference/arrays.ndarray.rst b/doc/source/reference/arrays.ndarray.rst
index 14d35271e..4c8bbf66d 100644
--- a/doc/source/reference/arrays.ndarray.rst
+++ b/doc/source/reference/arrays.ndarray.rst
@@ -119,12 +119,12 @@ strided scheme, and correspond to memory that can be *addressed* by the strides:
.. math::
- s_k^{\mathrm{column}} = \prod_{j=0}^{k-1} d_j ,
- \quad s_k^{\mathrm{row}} = \prod_{j=k+1}^{N-1} d_j .
+ s_k^{\mathrm{column}} = \mathrm{itemsize} \prod_{j=0}^{k-1} d_j ,
+ \quad s_k^{\mathrm{row}} = \mathrm{itemsize} \prod_{j=k+1}^{N-1} d_j .
.. index:: single-segment, contiguous, non-contiguous
-where :math:`d_j` `= self.itemsize * self.shape[j]`.
+where :math:`d_j` `= self.shape[j]`.
Both the C and Fortran orders are :term:`contiguous`, *i.e.,*
:term:`single-segment`, memory layouts, in which every part of the
@@ -595,8 +595,6 @@ Container customization: (see :ref:`Indexing <arrays.indexing>`)
ndarray.__len__
ndarray.__getitem__
ndarray.__setitem__
- ndarray.__getslice__
- ndarray.__setslice__
ndarray.__contains__
Conversion; the operations :func:`complex()`, :func:`int()`,
diff --git a/doc/source/reference/arrays.scalars.rst b/doc/source/reference/arrays.scalars.rst
index 4acaf1b3b..f76087ce2 100644
--- a/doc/source/reference/arrays.scalars.rst
+++ b/doc/source/reference/arrays.scalars.rst
@@ -248,7 +248,8 @@ Indexing
Array scalars can be indexed like 0-dimensional arrays: if *x* is an
array scalar,
-- ``x[()]`` returns a 0-dimensional :class:`ndarray`
+- ``x[()]`` returns a copy of array scalar
+- ``x[...]`` returns a 0-dimensional :class:`ndarray`
- ``x['field-name']`` returns the array scalar in the field *field-name*.
(*x* can have fields, for example, when it corresponds to a structured data type.)
@@ -282,10 +283,10 @@ Defining new types
==================
There are two ways to effectively define a new array scalar type
-(apart from composing structured types :ref:`dtypes <arrays.dtypes>` from
-the built-in scalar types): One way is to simply subclass the
-:class:`ndarray` and overwrite the methods of interest. This will work to
-a degree, but internally certain behaviors are fixed by the data type of
-the array. To fully customize the data type of an array you need to
-define a new data-type, and register it with NumPy. Such new types can only
+(apart from composing structured types :ref:`dtypes <arrays.dtypes>` from
+the built-in scalar types): One way is to simply subclass the
+:class:`ndarray` and overwrite the methods of interest. This will work to
+a degree, but internally certain behaviors are fixed by the data type of
+the array. To fully customize the data type of an array you need to
+define a new data-type, and register it with NumPy. Such new types can only
be defined in C, using the :ref:`NumPy C-API <c-api>`.
diff --git a/doc/source/reference/c-api.array.rst b/doc/source/reference/c-api.array.rst
index 3574282a4..2a7bb3a32 100644
--- a/doc/source/reference/c-api.array.rst
+++ b/doc/source/reference/c-api.array.rst
@@ -1686,12 +1686,12 @@ Shape Manipulation
different total number of elements then the old shape. If
reallocation is necessary, then *self* must own its data, have
*self* - ``>base==NULL``, have *self* - ``>weakrefs==NULL``, and
- (unless refcheck is 0) not be referenced by any other array. A
- reference to the new array is returned. The fortran argument can
- be :c:data:`NPY_ANYORDER`, :c:data:`NPY_CORDER`, or
- :c:data:`NPY_FORTRANORDER`. It currently has no effect. Eventually
+ (unless refcheck is 0) not be referenced by any other array.
+ The fortran argument can be :c:data:`NPY_ANYORDER`, :c:data:`NPY_CORDER`,
+ or :c:data:`NPY_FORTRANORDER`. It currently has no effect. Eventually
it could be used to determine how the resize operation should view
the data when constructing a differently-dimensioned array.
+ Returns None on success and NULL on error.
.. c:function:: PyObject* PyArray_Transpose(PyArrayObject* self, PyArray_Dims* permute)
diff --git a/doc/source/reference/c-api.iterator.rst b/doc/source/reference/c-api.iterator.rst
index b38c21390..679763067 100644
--- a/doc/source/reference/c-api.iterator.rst
+++ b/doc/source/reference/c-api.iterator.rst
@@ -461,6 +461,23 @@ Construction and Destruction
Then, call :c:func:`NpyIter_Reset` to allocate and fill the buffers
with their initial values.
+ .. c:var:: NPY_ITER_COPY_IF_OVERLAP
+
+ If any write operand has overlap with any read operand, eliminate all
+ overlap by making temporary copies (enabling UPDATEIFCOPY for write
+ operands, if necessary). A pair of operands has overlap if there is
+ a memory address that contains data common to both arrays.
+
+ Because exact overlap detection has exponential runtime
+ in the number of dimensions, the decision is made based
+ on heuristics, which has false positives (needless copies in unusual
+ cases) but has no false negatives.
+
+ If any read/write overlap exists, this flag ensures the result of the
+ operation is the same as if all operands were copied.
+ In cases where copies would need to be made, **the result of the
+ computation may be undefined without this flag!**
+
Flags that may be passed in ``op_flags[i]``, where ``0 <= i < nop``:
.. c:var:: NPY_ITER_READWRITE
@@ -591,6 +608,18 @@ Construction and Destruction
returns true from the corresponding element in the ARRAYMASK
operand.
+ .. c:var:: NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE
+
+ In memory overlap checks, assume that operands with
+ ``NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE`` enabled are accessed only
+ in the iterator order.
+
+ This enables the iterator to reason about data dependency,
+ possibly avoiding unnecessary copies.
+
+ This flag has effect only if ``NPY_ITER_COPY_IF_OVERLAP`` is enabled
+ on the iterator.
+
.. c:function:: NpyIter* NpyIter_AdvancedNew(npy_intp nop, PyArrayObject** op, npy_uint32 flags, NPY_ORDER order, NPY_CASTING casting, npy_uint32* op_flags, PyArray_Descr** op_dtypes, int oa_ndim, int** op_axes, npy_intp* itershape, npy_intp buffersize)
Extends :c:func:`NpyIter_MultiNew` with several advanced options providing
diff --git a/doc/source/reference/maskedarray.baseclass.rst b/doc/source/reference/maskedarray.baseclass.rst
index a1c90a45d..f35b0ea88 100644
--- a/doc/source/reference/maskedarray.baseclass.rst
+++ b/doc/source/reference/maskedarray.baseclass.rst
@@ -417,8 +417,6 @@ Container customization: (see :ref:`Indexing <arrays.indexing>`)
MaskedArray.__getitem__
MaskedArray.__setitem__
MaskedArray.__delitem__
- MaskedArray.__getslice__
- MaskedArray.__setslice__
MaskedArray.__contains__
diff --git a/doc/source/user/quickstart.rst b/doc/source/user/quickstart.rst
index 65840c724..f69eb3ace 100644
--- a/doc/source/user/quickstart.rst
+++ b/doc/source/user/quickstart.rst
@@ -713,27 +713,32 @@ Several arrays can be stacked together along different axes::
The function `column_stack`
stacks 1D arrays as columns into a 2D array. It is equivalent to
-`vstack` only for 1D arrays::
+`hstack` only for 2D arrays::
>>> from numpy import newaxis
- >>> np.column_stack((a,b)) # With 2D arrays
+ >>> np.column_stack((a,b)) # with 2D arrays
array([[ 8., 8., 1., 8.],
[ 0., 0., 0., 4.]])
>>> a = np.array([4.,2.])
- >>> b = np.array([2.,8.])
- >>> a[:,newaxis] # This allows to have a 2D columns vector
+ >>> b = np.array([3.,8.])
+ >>> np.column_stack((a,b)) # returns a 2D array
+ array([[ 4., 3.],
+ [ 2., 8.]])
+ >>> np.hstack((a,b)) # the result is different
+ array([ 4., 2., 3., 8.])
+ >>> a[:,newaxis] # this allows to have a 2D columns vector
array([[ 4.],
[ 2.]])
>>> np.column_stack((a[:,newaxis],b[:,newaxis]))
- array([[ 4., 2.],
+ array([[ 4., 3.],
+ [ 2., 8.]])
+ >>> np.hstack((a[:,newaxis],b[:,newaxis])) # the result is the same
+ array([[ 4., 3.],
[ 2., 8.]])
- >>> np.vstack((a[:,newaxis],b[:,newaxis])) # The behavior of vstack is different
- array([[ 4.],
- [ 2.],
- [ 2.],
- [ 8.]])
-For arrays of with more than two dimensions,
+On the other hand, the function `row_stack` is equivalent to `vstack`
+for any input arrays.
+In general, for arrays of with more than two dimensions,
`hstack` stacks along their second
axes, `vstack` stacks along their
first axes, and `concatenate`
diff --git a/numpy/add_newdocs.py b/numpy/add_newdocs.py
index 1d4bf4511..09f4e40c4 100644
--- a/numpy/add_newdocs.py
+++ b/numpy/add_newdocs.py
@@ -169,6 +169,10 @@ add_newdoc('numpy.core', 'nditer',
with one per iteration dimension, to be tracked.
* "common_dtype" causes all the operands to be converted to
a common data type, with copying or buffering as necessary.
+ * "copy_if_overlap" causes the iterator to determine if read
+ operands have overlap with write operands, and make temporary
+ copies as necessary to avoid overlap. False positives (needless
+ copying) are possible in some cases.
* "delay_bufalloc" delays allocation of the buffers until
a reset() call is made. Allows "allocate" operands to
be initialized before their values are copied into the buffers.
@@ -208,6 +212,9 @@ add_newdoc('numpy.core', 'nditer',
copies those elements indicated by this mask.
* 'writemasked' indicates that only elements where the chosen
'arraymask' operand is True will be written to.
+ * "overlap_assume_elementwise" can be used to mark operands that are
+ accessed only in the iterator order, to allow less conservative
+ copying when "copy_if_overlap" is present.
op_dtypes : dtype or tuple of dtype(s), optional
The required data type(s) of the operands. If copying or buffering
is enabled, the data will be converted to/from their original types.
@@ -5029,7 +5036,7 @@ add_newdoc('numpy.core.multiarray', 'digitize',
`bins` is monotonically decreasing. If values in `x` are beyond the
bounds of `bins`, 0 or ``len(bins)`` is returned as appropriate. If right
is True, then the right bin is closed so that the index ``i`` is such
- that ``bins[i-1] < x <= bins[i]`` or bins[i-1] >= x > bins[i]`` if `bins`
+ that ``bins[i-1] < x <= bins[i]`` or ``bins[i-1] >= x > bins[i]`` if `bins`
is monotonically increasing or decreasing, respectively.
Parameters
@@ -5060,7 +5067,7 @@ add_newdoc('numpy.core.multiarray', 'digitize',
See Also
--------
- bincount, histogram, unique
+ bincount, histogram, unique, searchsorted
Notes
-----
diff --git a/numpy/core/_methods.py b/numpy/core/_methods.py
index abfd0a3cc..c05316d18 100644
--- a/numpy/core/_methods.py
+++ b/numpy/core/_methods.py
@@ -72,10 +72,10 @@ def _mean(a, axis=None, dtype=None, out=None, keepdims=False):
ret = um.true_divide(
ret, rcount, out=ret, casting='unsafe', subok=False)
if is_float16_result and out is None:
- ret = a.dtype.type(ret)
+ ret = arr.dtype.type(ret)
elif hasattr(ret, 'dtype'):
if is_float16_result:
- ret = a.dtype.type(ret / rcount)
+ ret = arr.dtype.type(ret / rcount)
else:
ret = ret.dtype.type(ret / rcount)
else:
diff --git a/numpy/core/code_generators/cversions.txt b/numpy/core/code_generators/cversions.txt
index 9ade153f5..54140f24a 100644
--- a/numpy/core/code_generators/cversions.txt
+++ b/numpy/core/code_generators/cversions.txt
@@ -34,3 +34,6 @@
# Version 10 (NumPy 1.11) No change.
# Version 10 (NumPy 1.12) No change.
0x0000000a = 9b8bce614655d3eb02acddcb508203cb
+
+# Version 11 (NumPy 1.13) Added PyArray_MapIterArrayCopyIfOverlap
+0x0000000b = edb1ba83730c650fd9bc5772a919cda7
diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py
index 972966627..d1406e3b2 100644
--- a/numpy/core/code_generators/numpy_api.py
+++ b/numpy/core/code_generators/numpy_api.py
@@ -344,6 +344,8 @@ multiarray_funcs_api = {
# End 1.9 API
'PyArray_CheckAnyScalarExact': (300, NonNull(1)),
# End 1.10 API
+ 'PyArray_MapIterArrayCopyIfOverlap': (301,),
+ # End 1.13 API
}
ufunc_types_api = {
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index 4cb78e3fc..58f8696d2 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -1667,11 +1667,15 @@ def clip(a, a_min, a_max, out=None):
----------
a : array_like
Array containing elements to clip.
- a_min : scalar or array_like
- Minimum value.
- a_max : scalar or array_like
- Maximum value. If `a_min` or `a_max` are array_like, then they will
- be broadcasted to the shape of `a`.
+ a_min : scalar or array_like or `None`
+ Minimum value. If `None`, clipping is not performed on lower
+ interval edge. Not more than one of `a_min` and `a_max` may be
+ `None`.
+ a_max : scalar or array_like or `None`
+ Maximum value. If `None`, clipping is not performed on upper
+ interval edge. Not more than one of `a_min` and `a_max` may be
+ `None`. If `a_min` or `a_max` are array_like, then the three
+ arrays will be broadcasted to match their shapes.
out : ndarray, optional
The results will be placed in this array. It may be the input
array for in-place clipping. `out` must be of the right shape
@@ -1700,7 +1704,7 @@ def clip(a, a_min, a_max, out=None):
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
- >>> np.clip(a, [3,4,1,1,1,4,4,4,4,4], 8)
+ >>> np.clip(a, [3, 4, 1, 1, 1, 4, 4, 4, 4, 4], 8)
array([3, 4, 2, 3, 4, 5, 6, 7, 8, 8])
"""
diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py
index d4025cb3b..5b5e69352 100644
--- a/numpy/core/getlimits.py
+++ b/numpy/core/getlimits.py
@@ -5,23 +5,283 @@ from __future__ import division, absolute_import, print_function
__all__ = ['finfo', 'iinfo']
+import warnings
+
from .machar import MachAr
from . import numeric
from . import numerictypes as ntypes
-from .numeric import array
+from .numeric import array, inf
+from .umath import log10, exp2
+from . import umath
+
-def _frz(a):
+def _fr0(a):
"""fix rank-0 --> rank-1"""
if a.ndim == 0:
+ a = a.copy()
a.shape = (1,)
return a
+
+def _fr1(a):
+ """fix rank > 0 --> rank-0"""
+ if a.size == 1:
+ a = a.copy()
+ a.shape = ()
+ return a
+
+
_convert_to_float = {
ntypes.csingle: ntypes.single,
ntypes.complex_: ntypes.float_,
ntypes.clongfloat: ntypes.longfloat
}
+
+# Parameters for creating MachAr / MachAr-like objects
+_title_fmt = 'numpy {} precision floating point number'
+_MACHAR_PARAMS = {
+ ntypes.double: dict(
+ itype = ntypes.int64,
+ fmt = '%24.16e',
+ title = _title_fmt.format('double')),
+ ntypes.single: dict(
+ itype = ntypes.int32,
+ fmt = '%15.7e',
+ title = _title_fmt.format('single')),
+ ntypes.longdouble: dict(
+ itype = ntypes.longlong,
+ fmt = '%s',
+ title = _title_fmt.format('long double')),
+ ntypes.half: dict(
+ itype = ntypes.int16,
+ fmt = '%12.5e',
+ title = _title_fmt.format('half'))}
+
+
+class MachArLike(object):
+ """ Object to simulate MachAr instance """
+
+ def __init__(self,
+ ftype,
+ **kwargs):
+ params = _MACHAR_PARAMS[ftype]
+ float_conv = lambda v: array([v], ftype)
+ float_to_float = lambda v : _fr1(float_conv(v))
+ float_to_str = lambda v: (params['fmt'] % array(_fr0(v)[0], ftype))
+ self.title = params['title']
+ # Parameter types same as for discovered MachAr object.
+ self.epsilon = self.eps = float_to_float(kwargs.pop('eps'))
+ self.epsneg = float_to_float(kwargs.pop('epsneg'))
+ self.xmax = self.huge = float_to_float(kwargs.pop('huge'))
+ self.xmin = self.tiny = float_to_float(kwargs.pop('tiny'))
+ self.ibeta = params['itype'](kwargs.pop('ibeta'))
+ self.__dict__.update(kwargs)
+ self.precision = int(-log10(self.eps))
+ self.resolution = float_to_float(float_conv(10) ** (-self.precision))
+ self._str_eps = float_to_str(self.eps)
+ self._str_epsneg = float_to_str(self.epsneg)
+ self._str_xmin = float_to_str(self.xmin)
+ self._str_xmax = float_to_str(self.xmax)
+ self._str_resolution = float_to_str(self.resolution)
+
+
+# Known parameters for float16
+# See docstring of MachAr class for description of parameters.
+_f16 = ntypes.float16
+_float16_ma = MachArLike(_f16,
+ machep=-10,
+ negep=-11,
+ minexp=-14,
+ maxexp=16,
+ it=10,
+ iexp=5,
+ ibeta=2,
+ irnd=5,
+ ngrd=0,
+ eps=exp2(_f16(-10)),
+ epsneg=exp2(_f16(-11)),
+ huge=_f16(65504),
+ tiny=_f16(2 ** -14))
+
+# Known parameters for float32
+_f32 = ntypes.float32
+_float32_ma = MachArLike(_f32,
+ machep=-23,
+ negep=-24,
+ minexp=-126,
+ maxexp=128,
+ it=23,
+ iexp=8,
+ ibeta=2,
+ irnd=5,
+ ngrd=0,
+ eps=exp2(_f32(-23)),
+ epsneg=exp2(_f32(-24)),
+ huge=_f32((1 - 2 ** -24) * 2**128),
+ tiny=exp2(_f32(-126)))
+
+# Known parameters for float64
+_f64 = ntypes.float64
+_epsneg_f64 = 2.0 ** -53.0
+_tiny_f64 = 2.0 ** -1022.0
+_float64_ma = MachArLike(_f64,
+ machep=-52,
+ negep=-53,
+ minexp=-1022,
+ maxexp=1024,
+ it=52,
+ iexp=11,
+ ibeta=2,
+ irnd=5,
+ ngrd=0,
+ eps=2.0 ** -52.0,
+ epsneg=_epsneg_f64,
+ huge=(1.0 - _epsneg_f64) / _tiny_f64 * _f64(4),
+ tiny=_tiny_f64)
+
+# Known parameters for IEEE 754 128-bit binary float
+_ld = ntypes.longdouble
+_epsneg_f128 = exp2(_ld(-113))
+_tiny_f128 = exp2(_ld(-16382))
+# Ignore runtime error when this is not f128
+with numeric.errstate(all='ignore'):
+ _huge_f128 = (_ld(1) - _epsneg_f128) / _tiny_f128 * _ld(4)
+_float128_ma = MachArLike(_ld,
+ machep=-112,
+ negep=-113,
+ minexp=-16382,
+ maxexp=16384,
+ it=112,
+ iexp=15,
+ ibeta=2,
+ irnd=5,
+ ngrd=0,
+ eps=exp2(_ld(-112)),
+ epsneg=_epsneg_f128,
+ huge=_huge_f128,
+ tiny=_tiny_f128)
+
+# Known parameters for float80 (Intel 80-bit extended precision)
+_epsneg_f80 = exp2(_ld(-64))
+_tiny_f80 = exp2(_ld(-16382))
+# Ignore runtime error when this is not f80
+with numeric.errstate(all='ignore'):
+ _huge_f80 = (_ld(1) - _epsneg_f80) / _tiny_f80 * _ld(4)
+_float80_ma = MachArLike(_ld,
+ machep=-63,
+ negep=-64,
+ minexp=-16382,
+ maxexp=16384,
+ it=63,
+ iexp=15,
+ ibeta=2,
+ irnd=5,
+ ngrd=0,
+ eps=exp2(_ld(-63)),
+ epsneg=_epsneg_f80,
+ huge=_huge_f80,
+ tiny=_tiny_f80)
+
+# Guessed / known parameters for double double; see:
+# https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic
+# These numbers have the same exponent range as float64, but extended number of
+# digits in the significand.
+_huge_dd = (umath.nextafter(_ld(inf), _ld(0))
+ if hasattr(umath, 'nextafter') # Missing on some platforms?
+ else _float64_ma.huge)
+_float_dd_ma = MachArLike(_ld,
+ machep=-105,
+ negep=-106,
+ minexp=-1022,
+ maxexp=1024,
+ it=105,
+ iexp=11,
+ ibeta=2,
+ irnd=5,
+ ngrd=0,
+ eps=exp2(_ld(-105)),
+ epsneg= exp2(_ld(-106)),
+ huge=_huge_dd,
+ tiny=exp2(_ld(-1022)))
+
+
+# Key to identify the floating point type. Key is result of
+# ftype('-0.1').newbyteorder('<').tobytes()
+# See:
+# https://perl5.git.perl.org/perl.git/blob/3118d7d684b56cbeb702af874f4326683c45f045:/Configure
+_KNOWN_TYPES = {
+ b'\x9a\x99\x99\x99\x99\x99\xb9\xbf' : _float64_ma,
+ b'\xcd\xcc\xcc\xbd' : _float32_ma,
+ b'f\xae' : _float16_ma,
+ # float80, first 10 bytes containing actual storage
+ b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf' : _float80_ma,
+ # double double; low, high order (e.g. PPC 64)
+ b'\x9a\x99\x99\x99\x99\x99Y<\x9a\x99\x99\x99\x99\x99\xb9\xbf' :
+ _float_dd_ma,
+ # double double; high, low order (e.g. PPC 64 le)
+ b'\x9a\x99\x99\x99\x99\x99\xb9\xbf\x9a\x99\x99\x99\x99\x99Y<' :
+ _float_dd_ma,
+ # IEEE 754 128-bit binary float
+ b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf' :
+ _float128_ma,
+}
+
+
+def _get_machar(ftype):
+ """ Get MachAr instance or MachAr-like instance
+
+ Get parameters for floating point type, by first trying signatures of
+ various known floating point types, then, if none match, attempting to
+ identify parameters by analysis.
+
+ Parameters
+ ----------
+ ftype : class
+ Numpy floating point type class (e.g. ``np.float64``)
+
+ Returns
+ -------
+ ma_like : instance of :class:`MachAr` or :class:`MachArLike`
+ Object giving floating point parameters for `ftype`.
+
+ Warns
+ -----
+ UserWarning
+ If the binary signature of the float type is not in the dictionary of
+ known float types.
+ """
+ params = _MACHAR_PARAMS.get(ftype)
+ if params is None:
+ raise ValueError(repr(ftype))
+ # Detect known / suspected types
+ key = ftype('-0.1').newbyteorder('<').tobytes()
+ ma_like = _KNOWN_TYPES.get(key)
+ # Could be 80 bit == 10 byte extended precision, where last bytes can be
+ # random garbage. Try comparing first 10 bytes to pattern.
+ if ma_like is None and ftype == ntypes.longdouble:
+ ma_like = _KNOWN_TYPES.get(key[:10])
+ if ma_like is not None:
+ return ma_like
+ # Fall back to parameter discovery
+ warnings.warn(
+ 'Signature {} for {} does not match any known type: '
+ 'falling back to type probe function'.format(key, ftype),
+ UserWarning, stacklevel=2)
+ return _discovered_machar(ftype)
+
+
+def _discovered_machar(ftype):
+ """ Create MachAr instance with found information on float types
+ """
+ params = _MACHAR_PARAMS[ftype]
+ return MachAr(lambda v: array([v], ftype),
+ lambda v:_fr0(v.astype(params['itype']))[0],
+ lambda v:array(_fr0(v)[0], ftype),
+ lambda v: params['fmt'] % array(_fr0(v)[0], ftype),
+ params['title'])
+
+
class finfo(object):
"""
finfo(dtype)
@@ -128,30 +388,7 @@ class finfo(object):
def _init(self, dtype):
self.dtype = numeric.dtype(dtype)
- if dtype is ntypes.double:
- itype = ntypes.int64
- fmt = '%24.16e'
- precname = 'double'
- elif dtype is ntypes.single:
- itype = ntypes.int32
- fmt = '%15.7e'
- precname = 'single'
- elif dtype is ntypes.longdouble:
- itype = ntypes.longlong
- fmt = '%s'
- precname = 'long double'
- elif dtype is ntypes.half:
- itype = ntypes.int16
- fmt = '%12.5e'
- precname = 'half'
- else:
- raise ValueError(repr(dtype))
-
- machar = MachAr(lambda v:array([v], dtype),
- lambda v:_frz(v.astype(itype))[0],
- lambda v:array(_frz(v)[0], dtype),
- lambda v: fmt % array(_frz(v)[0], dtype),
- 'numpy %s precision floating point number' % precname)
+ machar = _get_machar(dtype)
for word in ['precision', 'iexp',
'maxexp', 'minexp', 'negep',
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h
index a9848f434..7f6fe6524 100644
--- a/numpy/core/include/numpy/ndarraytypes.h
+++ b/numpy/core/include/numpy/ndarraytypes.h
@@ -1008,6 +1008,12 @@ typedef void (NpyIter_GetMultiIndexFunc)(NpyIter *iter,
#define NPY_ITER_DELAY_BUFALLOC 0x00000800
/* When NPY_KEEPORDER is specified, disable reversing negative-stride axes */
#define NPY_ITER_DONT_NEGATE_STRIDES 0x00001000
+/*
+ * If output operands overlap with other operands (based on heuristics that
+ * has false positives but no false negatives), make temporary copies to
+ * eliminate overlap.
+ */
+#define NPY_ITER_COPY_IF_OVERLAP 0x00002000
/*** Per-operand flags that may be passed to the iterator constructors ***/
@@ -1039,6 +1045,8 @@ typedef void (NpyIter_GetMultiIndexFunc)(NpyIter *iter,
#define NPY_ITER_WRITEMASKED 0x10000000
/* This array is the mask for all WRITEMASKED operands */
#define NPY_ITER_ARRAYMASK 0x20000000
+/* Assume iterator order data access for COPY_IF_OVERLAP */
+#define NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE 0x40000000
#define NPY_ITER_GLOBAL_FLAGS 0x0000ffff
#define NPY_ITER_PER_OP_FLAGS 0xffff0000
diff --git a/numpy/core/memmap.py b/numpy/core/memmap.py
index b77deb59a..f07cf78ee 100644
--- a/numpy/core/memmap.py
+++ b/numpy/core/memmap.py
@@ -260,11 +260,11 @@ class memmap(ndarray):
start = offset - offset % mmap.ALLOCATIONGRANULARITY
bytes -= start
- offset -= start
+ array_offset = offset - start
mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
self = ndarray.__new__(subtype, shape, dtype=descr, buffer=mm,
- offset=offset, order=order)
+ offset=array_offset, order=order)
self._mmap = mm
self.offset = offset
self.mode = mode
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py
index b90b0a9c9..97d19f008 100644
--- a/numpy/core/numeric.py
+++ b/numpy/core/numeric.py
@@ -2089,15 +2089,12 @@ def indices(dimensions, dtype=int):
"""
dimensions = tuple(dimensions)
N = len(dimensions)
- if N == 0:
- return array([], dtype=dtype)
+ shape = (1,)*N
res = empty((N,)+dimensions, dtype=dtype)
for i, dim in enumerate(dimensions):
- tmp = arange(dim, dtype=dtype)
- tmp.shape = (1,)*i + (dim,)+(1,)*(N-i-1)
- newdim = dimensions[:i] + (1,) + dimensions[i+1:]
- val = zeros(newdim, dtype)
- add(tmp, val, res[i])
+ res[i] = arange(dim, dtype=dtype).reshape(
+ shape[:i] + (dim,) + shape[i+1:]
+ )
return res
diff --git a/numpy/core/records.py b/numpy/core/records.py
index 3bee394cd..91b70614c 100644
--- a/numpy/core/records.py
+++ b/numpy/core/records.py
@@ -513,13 +513,8 @@ class recarray(ndarray):
return obj
def __repr__(self):
- # get data/shape string. logic taken from numeric.array_repr
- if self.size > 0 or self.shape == (0,):
- lst = sb.array2string(self, separator=', ')
- else:
- # show zero-length shape unless it is (0,)
- lst = "[], shape=%s" % (repr(self.shape),)
+ repr_dtype = self.dtype
if (self.dtype.type is record
or (not issubclass(self.dtype.type, nt.void))):
# If this is a full record array (has numpy.record dtype),
@@ -527,19 +522,26 @@ class recarray(ndarray):
# represent it using the rec.array function. Since rec.array
# converts dtype to a numpy.record for us, convert back
# to non-record before printing
- plain_dtype = self.dtype
- if plain_dtype.type is record:
- plain_dtype = sb.dtype((nt.void, plain_dtype))
- lf = '\n'+' '*len("rec.array(")
- return ('rec.array(%s, %sdtype=%s)' %
- (lst, lf, plain_dtype))
+ if repr_dtype.type is record:
+ repr_dtype = sb.dtype((nt.void, repr_dtype))
+ prefix = "rec.array("
+ fmt = 'rec.array(%s, %sdtype=%s)'
else:
# otherwise represent it using np.array plus a view
# This should only happen if the user is playing
# strange games with dtypes.
- lf = '\n'+' '*len("array(")
- return ('array(%s, %sdtype=%s).view(numpy.recarray)' %
- (lst, lf, str(self.dtype)))
+ prefix = "array("
+ fmt = 'array(%s, %sdtype=%s).view(numpy.recarray)'
+
+ # get data/shape string. logic taken from numeric.array_repr
+ if self.size > 0 or self.shape == (0,):
+ lst = sb.array2string(self, separator=', ', prefix=prefix)
+ else:
+ # show zero-length shape unless it is (0,)
+ lst = "[], shape=%s" % (repr(self.shape),)
+
+ lf = '\n'+' '*len(prefix)
+ return fmt % (lst, lf, repr_dtype)
def field(self, attr, val=None):
if isinstance(attr, int):
@@ -624,7 +626,6 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None,
return _array
-# shape must be 1-d if you use list of lists...
def fromrecords(recList, dtype=None, shape=None, formats=None, names=None,
titles=None, aligned=False, byteorder=None):
""" create a recarray from a list of records in text form
@@ -655,10 +656,9 @@ def fromrecords(recList, dtype=None, shape=None, formats=None, names=None,
[(456, 'dbe', 1.2) (2, 'de', 1.3)]
"""
- nfields = len(recList[0])
if formats is None and dtype is None: # slower
obj = sb.array(recList, dtype=object)
- arrlist = [sb.array(obj[..., i].tolist()) for i in range(nfields)]
+ arrlist = [sb.array(obj[..., i].tolist()) for i in range(obj.shape[-1])]
return fromarrays(arrlist, formats=formats, shape=shape, names=names,
titles=titles, aligned=aligned, byteorder=byteorder)
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 01070cc74..f45042bec 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -901,7 +901,8 @@ def configuration(parent_package='',top_path=None):
join('src', 'umath', 'loops.c.src'),
join('src', 'umath', 'ufunc_object.c'),
join('src', 'umath', 'scalarmath.c.src'),
- join('src', 'umath', 'ufunc_type_resolution.c')]
+ join('src', 'umath', 'ufunc_type_resolution.c'),
+ join('src', 'private', 'mem_overlap.c')]
umath_deps = [
generate_umath_py,
@@ -911,6 +912,8 @@ def configuration(parent_package='',top_path=None):
join('src', 'private', 'templ_common.h.src'),
join('src', 'umath', 'simd.inc.src'),
join(codegen_dir, 'generate_ufunc_api.py'),
+ join('src', 'private', 'lowlevel_strided_loops.h'),
+ join('src', 'private', 'mem_overlap.h'),
join('src', 'private', 'ufunc_override.h')] + npymath_sources
config.add_extension('umath',
diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py
index 18066d991..357051cdb 100644
--- a/numpy/core/setup_common.py
+++ b/numpy/core/setup_common.py
@@ -38,7 +38,8 @@ C_ABI_VERSION = 0x01000009
# 0x0000000a - 1.10.x
# 0x0000000a - 1.11.x
# 0x0000000a - 1.12.x
-C_API_VERSION = 0x0000000a
+# 0x0000000b - 1.13.x
+C_API_VERSION = 0x0000000b
class MismatchCAPIWarning(Warning):
pass
@@ -130,6 +131,8 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
# broken on OSX 10.11, make sure its not optimized away
("volatile int r = __builtin_cpu_supports", '"sse"',
"stdio.h", "__BUILTIN_CPU_SUPPORTS"),
+ # MMX only needed for icc, but some clangs don't have it
+ ("_m_from_int64", '0', "emmintrin.h"),
("_mm_load_ps", '(float*)0', "xmmintrin.h"), # SSE
("_mm_prefetch", '(float*)0, _MM_HINT_NTA',
"xmmintrin.h"), # SSE
diff --git a/numpy/core/src/multiarray/cblasfuncs.c b/numpy/core/src/multiarray/cblasfuncs.c
index ef05c7205..4b11be947 100644
--- a/numpy/core/src/multiarray/cblasfuncs.c
+++ b/numpy/core/src/multiarray/cblasfuncs.c
@@ -12,6 +12,7 @@
#include "npy_cblas.h"
#include "arraytypes.h"
#include "common.h"
+#include "mem_overlap.h"
/*
@@ -242,7 +243,7 @@ NPY_NO_EXPORT PyObject *
cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
PyArrayObject *out)
{
- PyArrayObject *ret = NULL;
+ PyArrayObject *result = NULL, *out_buf = NULL;
int j, lda, ldb;
npy_intp l;
int nd;
@@ -412,25 +413,50 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
goto fail;
}
}
+
+ /* check for memory overlap */
+ if (!(solve_may_share_memory(out, ap1, 1) == 0 &&
+ solve_may_share_memory(out, ap2, 1) == 0)) {
+ /* allocate temporary output array */
+ out_buf = (PyArrayObject *)PyArray_NewLikeArray(out, NPY_CORDER,
+ NULL, 0);
+ if (out_buf == NULL) {
+ goto fail;
+ }
+
+ /* set copy-back */
+ Py_INCREF(out);
+ if (PyArray_SetUpdateIfCopyBase(out_buf, out) < 0) {
+ Py_DECREF(out);
+ goto fail;
+ }
+ }
+ else {
+ Py_INCREF(out);
+ out_buf = out;
+ }
Py_INCREF(out);
- ret = out;
+ result = out;
}
else {
PyObject *tmp = (PyObject *)(prior2 > prior1 ? ap2 : ap1);
- ret = (PyArrayObject *)PyArray_New(subtype, nd, dimensions,
- typenum, NULL, NULL, 0, 0, tmp);
- }
+ out_buf = (PyArrayObject *)PyArray_New(subtype, nd, dimensions,
+ typenum, NULL, NULL, 0, 0, tmp);
+ if (out_buf == NULL) {
+ goto fail;
+ }
- if (ret == NULL) {
- goto fail;
+ Py_INCREF(out_buf);
+ result = out_buf;
}
- numbytes = PyArray_NBYTES(ret);
- memset(PyArray_DATA(ret), 0, numbytes);
+
+ numbytes = PyArray_NBYTES(out_buf);
+ memset(PyArray_DATA(out_buf), 0, numbytes);
if (numbytes == 0 || l == 0) {
Py_DECREF(ap1);
Py_DECREF(ap2);
- return PyArray_Return(ret);
+ return PyArray_Return(out_buf);
}
if (ap2shape == _scalar) {
@@ -443,7 +469,7 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
if (typenum == NPY_DOUBLE) {
if (l == 1) {
- *((double *)PyArray_DATA(ret)) = *((double *)PyArray_DATA(ap2)) *
+ *((double *)PyArray_DATA(out_buf)) = *((double *)PyArray_DATA(ap2)) *
*((double *)PyArray_DATA(ap1));
}
else if (ap1shape != _matrix) {
@@ -451,26 +477,26 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
*((double *)PyArray_DATA(ap2)),
(double *)PyArray_DATA(ap1),
ap1stride/sizeof(double),
- (double *)PyArray_DATA(ret), 1);
+ (double *)PyArray_DATA(out_buf), 1);
}
else {
- int maxind, oind, i, a1s, rets;
- char *ptr, *rptr;
+ int maxind, oind, i, a1s, outs;
+ char *ptr, *optr;
double val;
maxind = (PyArray_DIM(ap1, 0) >= PyArray_DIM(ap1, 1) ? 0 : 1);
oind = 1 - maxind;
ptr = PyArray_DATA(ap1);
- rptr = PyArray_DATA(ret);
+ optr = PyArray_DATA(out_buf);
l = PyArray_DIM(ap1, maxind);
val = *((double *)PyArray_DATA(ap2));
a1s = PyArray_STRIDE(ap1, maxind) / sizeof(double);
- rets = PyArray_STRIDE(ret, maxind) / sizeof(double);
+ outs = PyArray_STRIDE(out_buf, maxind) / sizeof(double);
for (i = 0; i < PyArray_DIM(ap1, oind); i++) {
cblas_daxpy(l, val, (double *)ptr, a1s,
- (double *)rptr, rets);
+ (double *)optr, outs);
ptr += PyArray_STRIDE(ap1, oind);
- rptr += PyArray_STRIDE(ret, oind);
+ optr += PyArray_STRIDE(out_buf, oind);
}
}
}
@@ -480,7 +506,7 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
ptr1 = (npy_cdouble *)PyArray_DATA(ap2);
ptr2 = (npy_cdouble *)PyArray_DATA(ap1);
- res = (npy_cdouble *)PyArray_DATA(ret);
+ res = (npy_cdouble *)PyArray_DATA(out_buf);
res->real = ptr1->real * ptr2->real - ptr1->imag * ptr2->imag;
res->imag = ptr1->real * ptr2->imag + ptr1->imag * ptr2->real;
}
@@ -489,32 +515,32 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
(double *)PyArray_DATA(ap2),
(double *)PyArray_DATA(ap1),
ap1stride/sizeof(npy_cdouble),
- (double *)PyArray_DATA(ret), 1);
+ (double *)PyArray_DATA(out_buf), 1);
}
else {
- int maxind, oind, i, a1s, rets;
- char *ptr, *rptr;
+ int maxind, oind, i, a1s, outs;
+ char *ptr, *optr;
double *pval;
maxind = (PyArray_DIM(ap1, 0) >= PyArray_DIM(ap1, 1) ? 0 : 1);
oind = 1 - maxind;
ptr = PyArray_DATA(ap1);
- rptr = PyArray_DATA(ret);
+ optr = PyArray_DATA(out_buf);
l = PyArray_DIM(ap1, maxind);
pval = (double *)PyArray_DATA(ap2);
a1s = PyArray_STRIDE(ap1, maxind) / sizeof(npy_cdouble);
- rets = PyArray_STRIDE(ret, maxind) / sizeof(npy_cdouble);
+ outs = PyArray_STRIDE(out_buf, maxind) / sizeof(npy_cdouble);
for (i = 0; i < PyArray_DIM(ap1, oind); i++) {
cblas_zaxpy(l, pval, (double *)ptr, a1s,
- (double *)rptr, rets);
+ (double *)optr, outs);
ptr += PyArray_STRIDE(ap1, oind);
- rptr += PyArray_STRIDE(ret, oind);
+ optr += PyArray_STRIDE(out_buf, oind);
}
}
}
else if (typenum == NPY_FLOAT) {
if (l == 1) {
- *((float *)PyArray_DATA(ret)) = *((float *)PyArray_DATA(ap2)) *
+ *((float *)PyArray_DATA(out_buf)) = *((float *)PyArray_DATA(ap2)) *
*((float *)PyArray_DATA(ap1));
}
else if (ap1shape != _matrix) {
@@ -522,26 +548,26 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
*((float *)PyArray_DATA(ap2)),
(float *)PyArray_DATA(ap1),
ap1stride/sizeof(float),
- (float *)PyArray_DATA(ret), 1);
+ (float *)PyArray_DATA(out_buf), 1);
}
else {
- int maxind, oind, i, a1s, rets;
- char *ptr, *rptr;
+ int maxind, oind, i, a1s, outs;
+ char *ptr, *optr;
float val;
maxind = (PyArray_DIM(ap1, 0) >= PyArray_DIM(ap1, 1) ? 0 : 1);
oind = 1 - maxind;
ptr = PyArray_DATA(ap1);
- rptr = PyArray_DATA(ret);
+ optr = PyArray_DATA(out_buf);
l = PyArray_DIM(ap1, maxind);
val = *((float *)PyArray_DATA(ap2));
a1s = PyArray_STRIDE(ap1, maxind) / sizeof(float);
- rets = PyArray_STRIDE(ret, maxind) / sizeof(float);
+ outs = PyArray_STRIDE(out_buf, maxind) / sizeof(float);
for (i = 0; i < PyArray_DIM(ap1, oind); i++) {
cblas_saxpy(l, val, (float *)ptr, a1s,
- (float *)rptr, rets);
+ (float *)optr, outs);
ptr += PyArray_STRIDE(ap1, oind);
- rptr += PyArray_STRIDE(ret, oind);
+ optr += PyArray_STRIDE(out_buf, oind);
}
}
}
@@ -551,7 +577,7 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
ptr1 = (npy_cfloat *)PyArray_DATA(ap2);
ptr2 = (npy_cfloat *)PyArray_DATA(ap1);
- res = (npy_cfloat *)PyArray_DATA(ret);
+ res = (npy_cfloat *)PyArray_DATA(out_buf);
res->real = ptr1->real * ptr2->real - ptr1->imag * ptr2->imag;
res->imag = ptr1->real * ptr2->imag + ptr1->imag * ptr2->real;
}
@@ -560,26 +586,26 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
(float *)PyArray_DATA(ap2),
(float *)PyArray_DATA(ap1),
ap1stride/sizeof(npy_cfloat),
- (float *)PyArray_DATA(ret), 1);
+ (float *)PyArray_DATA(out_buf), 1);
}
else {
- int maxind, oind, i, a1s, rets;
- char *ptr, *rptr;
+ int maxind, oind, i, a1s, outs;
+ char *ptr, *optr;
float *pval;
maxind = (PyArray_DIM(ap1, 0) >= PyArray_DIM(ap1, 1) ? 0 : 1);
oind = 1 - maxind;
ptr = PyArray_DATA(ap1);
- rptr = PyArray_DATA(ret);
+ optr = PyArray_DATA(out_buf);
l = PyArray_DIM(ap1, maxind);
pval = (float *)PyArray_DATA(ap2);
a1s = PyArray_STRIDE(ap1, maxind) / sizeof(npy_cfloat);
- rets = PyArray_STRIDE(ret, maxind) / sizeof(npy_cfloat);
+ outs = PyArray_STRIDE(out_buf, maxind) / sizeof(npy_cfloat);
for (i = 0; i < PyArray_DIM(ap1, oind); i++) {
cblas_caxpy(l, pval, (float *)ptr, a1s,
- (float *)rptr, rets);
+ (float *)optr, outs);
ptr += PyArray_STRIDE(ap1, oind);
- rptr += PyArray_STRIDE(ret, oind);
+ optr += PyArray_STRIDE(out_buf, oind);
}
}
}
@@ -592,7 +618,7 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
blas_dot(typenum, l,
PyArray_DATA(ap1), PyArray_STRIDE(ap1, (ap1shape == _row)),
PyArray_DATA(ap2), PyArray_STRIDE(ap2, 0),
- PyArray_DATA(ret));
+ PyArray_DATA(out_buf));
NPY_END_ALLOW_THREADS;
}
else if (ap1shape == _matrix && ap2shape != _matrix) {
@@ -620,7 +646,7 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
lda = (PyArray_DIM(ap1, 0) > 1 ? PyArray_DIM(ap1, 0) : 1);
}
ap2s = PyArray_STRIDE(ap2, 0) / PyArray_ITEMSIZE(ap2);
- gemv(typenum, Order, CblasNoTrans, ap1, lda, ap2, ap2s, ret);
+ gemv(typenum, Order, CblasNoTrans, ap1, lda, ap2, ap2s, out_buf);
NPY_END_ALLOW_THREADS;
}
else if (ap1shape != _matrix && ap2shape == _matrix) {
@@ -652,7 +678,7 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
else {
ap1s = PyArray_STRIDE(ap1, 0) / PyArray_ITEMSIZE(ap1);
}
- gemv(typenum, Order, CblasTrans, ap2, lda, ap1, ap1s, ret);
+ gemv(typenum, Order, CblasTrans, ap2, lda, ap1, ap1s, out_buf);
NPY_END_ALLOW_THREADS;
}
else {
@@ -726,15 +752,15 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
((Trans1 == CblasNoTrans) ^ (Trans2 == CblasNoTrans))
) {
if (Trans1 == CblasNoTrans) {
- syrk(typenum, Order, Trans1, N, M, ap1, lda, ret);
+ syrk(typenum, Order, Trans1, N, M, ap1, lda, out_buf);
}
else {
- syrk(typenum, Order, Trans1, N, M, ap2, ldb, ret);
+ syrk(typenum, Order, Trans1, N, M, ap2, ldb, out_buf);
}
}
else {
gemm(typenum, Order, Trans1, Trans2, L, N, M, ap1, lda, ap2, ldb,
- ret);
+ out_buf);
}
NPY_END_ALLOW_THREADS;
}
@@ -742,11 +768,16 @@ cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,
Py_DECREF(ap1);
Py_DECREF(ap2);
- return PyArray_Return(ret);
+
+ /* Trigger possible copyback into `result` */
+ Py_DECREF(out_buf);
+
+ return PyArray_Return(result);
fail:
Py_XDECREF(ap1);
Py_XDECREF(ap2);
- Py_XDECREF(ret);
+ Py_XDECREF(out_buf);
+ Py_XDECREF(result);
return NULL;
}
diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c
index f2323d9e2..7ff803f96 100644
--- a/numpy/core/src/multiarray/compiled_base.c
+++ b/numpy/core/src/multiarray/compiled_base.c
@@ -9,6 +9,7 @@
#include "numpy/npy_math.h"
#include "npy_config.h"
#include "templ_common.h" /* for npy_mul_with_overflow_intp */
+#include "lowlevel_strided_loops.h" /* for npy_bswap8 */
/*
@@ -1475,6 +1476,9 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
Py_RETURN_NONE;
}
+#if defined NPY_HAVE_SSE2_INTRINSICS
+#include <emmintrin.h>
+#endif
/*
* This function packs boolean values in the input array into the bits of a
@@ -1497,13 +1501,41 @@ pack_inner(const char *inptr,
* No: move on
* Every 8th value, set the value of build and increment the outptr
*/
- npy_intp index;
+ npy_intp index = 0;
int remain = n_in % 8; /* uneven bits */
+#if defined NPY_HAVE_SSE2_INTRINSICS && defined HAVE__M_FROM_INT64
+ if (in_stride == 1 && element_size == 1 && n_out > 2) {
+ __m128i zero = _mm_setzero_si128();
+ /* don't handle non-full 8-byte remainder */
+ npy_intp vn_out = n_out - (remain ? 1 : 0);
+ vn_out -= (vn_out & 1);
+ for (index = 0; index < vn_out; index += 2) {
+ unsigned int r;
+ /* swap as packbits is "big endian", note x86 can load unaligned */
+ npy_uint64 a = npy_bswap8(*(npy_uint64*)inptr);
+ npy_uint64 b = npy_bswap8(*(npy_uint64*)(inptr + 8));
+ __m128i v = _mm_set_epi64(_m_from_int64(b), _m_from_int64(a));
+ /* false -> 0x00 and true -> 0xFF (there is no cmpneq) */
+ v = _mm_cmpeq_epi8(v, zero);
+ v = _mm_cmpeq_epi8(v, zero);
+ /* extract msb of 16 bytes and pack it into 16 bit */
+ r = _mm_movemask_epi8(v);
+ /* store result */
+ memcpy(outptr, &r, 1);
+ outptr += out_stride;
+ memcpy(outptr, (char*)&r + 1, 1);
+ outptr += out_stride;
+ inptr += 16;
+ }
+ }
+#endif
+
if (remain == 0) { /* assumes n_in > 0 */
remain = 8;
}
- for (index = 0; index < n_out; index++) {
+ /* don't reset index to handle remainder of above block */
+ for (; index < n_out; index++) {
char build = 0;
int i, maxi;
npy_intp j;
@@ -1628,6 +1660,8 @@ fail:
static PyObject *
unpack_bits(PyObject *input, int axis)
{
+ static int unpack_init = 0;
+ static char unpack_lookup[256][8];
PyArrayObject *inp;
PyArrayObject *new = NULL;
PyArrayObject *out = NULL;
@@ -1693,6 +1727,28 @@ unpack_bits(PyObject *input, int axis)
goto fail;
}
+ /* setup lookup table under GIL, big endian 0..256 as bytes */
+ if (unpack_init == 0) {
+ npy_uint64 j;
+ npy_uint64 * unpack_lookup_64 = (npy_uint64 *)unpack_lookup;
+ for (j=0; j < 256; j++) {
+ npy_uint64 v = 0;
+ v |= (npy_uint64)((j & 1) == 1);
+ v |= (npy_uint64)((j & 2) == 2) << 8;
+ v |= (npy_uint64)((j & 4) == 4) << 16;
+ v |= (npy_uint64)((j & 8) == 8) << 24;
+ v |= (npy_uint64)((j & 16) == 16) << 32;
+ v |= (npy_uint64)((j & 32) == 32) << 40;
+ v |= (npy_uint64)((j & 64) == 64) << 48;
+ v |= (npy_uint64)((j & 128) == 128) << 56;
+#if NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN
+ v = npy_bswap8(v);
+#endif
+ unpack_lookup_64[j] = v;
+ }
+ unpack_init = 1;
+ }
+
NPY_BEGIN_THREADS_THRESHOLDED(PyArray_DIM(new, axis));
n_in = PyArray_DIM(new, axis);
@@ -1704,15 +1760,25 @@ unpack_bits(PyObject *input, int axis)
unsigned const char *inptr = PyArray_ITER_DATA(it);
char *outptr = PyArray_ITER_DATA(ot);
- for (index = 0; index < n_in; index++) {
- unsigned char mask = 128;
+ if (out_stride == 1) {
+ /* for unity stride we can just copy out of the lookup table */
+ for (index = 0; index < n_in; index++) {
+ memcpy(outptr, unpack_lookup[*inptr], 8);
+ outptr += 8;
+ inptr += in_stride;
+ }
+ }
+ else {
+ for (index = 0; index < n_in; index++) {
+ unsigned char mask = 128;
- for (i = 0; i < 8; i++) {
- *outptr = ((mask & (*inptr)) != 0);
- outptr += out_stride;
- mask >>= 1;
+ for (i = 0; i < 8; i++) {
+ *outptr = ((mask & (*inptr)) != 0);
+ outptr += out_stride;
+ mask >>= 1;
+ }
+ inptr += in_stride;
}
- inptr += in_stride;
}
PyArray_ITER_NEXT(it);
PyArray_ITER_NEXT(ot);
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 9fa9ad088..6c2186f9c 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1041,8 +1041,11 @@ _convert_from_dict(PyObject *obj, int align)
}
n = PyObject_Length(names);
offsets = Borrowed_PyMapping_GetItemString(obj, "offsets");
+ if (!offsets) {
+ PyErr_Clear();
+ }
titles = Borrowed_PyMapping_GetItemString(obj, "titles");
- if (!offsets || !titles) {
+ if (!titles) {
PyErr_Clear();
}
@@ -1097,6 +1100,8 @@ _convert_from_dict(PyObject *obj, int align)
tup = PyTuple_New(len);
descr = PyObject_GetItem(descrs, ind);
if (!descr) {
+ Py_DECREF(tup);
+ Py_DECREF(ind);
goto fail;
}
if (align) {
@@ -1120,17 +1125,23 @@ _convert_from_dict(PyObject *obj, int align)
long offset;
off = PyObject_GetItem(offsets, ind);
if (!off) {
+ Py_DECREF(tup);
+ Py_DECREF(ind);
goto fail;
}
offset = PyArray_PyIntAsInt(off);
if (offset == -1 && PyErr_Occurred()) {
Py_DECREF(off);
+ Py_DECREF(tup);
+ Py_DECREF(ind);
goto fail;
}
Py_DECREF(off);
if (offset < 0) {
PyErr_Format(PyExc_ValueError, "offset %d cannot be negative",
(int)offset);
+ Py_DECREF(tup);
+ Py_DECREF(ind);
goto fail;
}
@@ -1159,14 +1170,20 @@ _convert_from_dict(PyObject *obj, int align)
PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(totalsize));
totalsize += newdescr->elsize;
}
+ if (ret == NPY_FAIL) {
+ Py_DECREF(ind);
+ Py_DECREF(tup);
+ goto fail;
+ }
if (len == 3) {
PyTuple_SET_ITEM(tup, 2, title);
}
name = PyObject_GetItem(names, ind);
+ Py_DECREF(ind);
if (!name) {
+ Py_DECREF(tup);
goto fail;
}
- Py_DECREF(ind);
#if defined(NPY_PY3K)
if (!PyUString_Check(name)) {
#else
@@ -1174,14 +1191,16 @@ _convert_from_dict(PyObject *obj, int align)
#endif
PyErr_SetString(PyExc_ValueError,
"field names must be strings");
- ret = NPY_FAIL;
+ Py_DECREF(tup);
+ goto fail;
}
/* Insert into dictionary */
if (PyDict_GetItem(fields, name) != NULL) {
PyErr_SetString(PyExc_ValueError,
"name already used as a name or title");
- ret = NPY_FAIL;
+ Py_DECREF(tup);
+ goto fail;
}
PyDict_SetItem(fields, name, tup);
Py_DECREF(name);
@@ -1194,7 +1213,8 @@ _convert_from_dict(PyObject *obj, int align)
if (PyDict_GetItem(fields, title) != NULL) {
PyErr_SetString(PyExc_ValueError,
"title already used as a name or title.");
- ret=NPY_FAIL;
+ Py_DECREF(tup);
+ goto fail;
}
PyDict_SetItem(fields, title, tup);
}
@@ -3651,6 +3671,31 @@ arraydescr_richcompare(PyArray_Descr *self, PyObject *other, int cmp_op)
return result;
}
+static int
+descr_nonzero(PyObject *self)
+{
+ /* `bool(np.dtype(...)) == True` for all dtypes. Needed to override default
+ * nonzero implementation, which checks if `len(object) > 0`. */
+ return 1;
+}
+
+static PyNumberMethods descr_as_number = {
+ (binaryfunc)0, /* nb_add */
+ (binaryfunc)0, /* nb_subtract */
+ (binaryfunc)0, /* nb_multiply */
+ #if defined(NPY_PY3K)
+ #else
+ (binaryfunc)0, /* nb_divide */
+ #endif
+ (binaryfunc)0, /* nb_remainder */
+ (binaryfunc)0, /* nb_divmod */
+ (ternaryfunc)0, /* nb_power */
+ (unaryfunc)0, /* nb_negative */
+ (unaryfunc)0, /* nb_positive */
+ (unaryfunc)0, /* nb_absolute */
+ (inquiry)descr_nonzero, /* nb_nonzero */
+};
+
/*************************************************************************
**************** Implement Mapping Protocol ***************************
*************************************************************************/
@@ -3800,7 +3845,7 @@ NPY_NO_EXPORT PyTypeObject PyArrayDescr_Type = {
0, /* tp_compare */
#endif
(reprfunc)arraydescr_repr, /* tp_repr */
- 0, /* tp_as_number */
+ &descr_as_number, /* tp_as_number */
&descr_as_sequence, /* tp_as_sequence */
&descr_as_mapping, /* tp_as_mapping */
0, /* tp_hash */
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c
index 70affbc9b..7a009d237 100644
--- a/numpy/core/src/multiarray/mapping.c
+++ b/numpy/core/src/multiarray/mapping.c
@@ -19,6 +19,7 @@
#include "mapping.h"
#include "lowlevel_strided_loops.h"
#include "item_selection.h"
+#include "mem_overlap.h"
#define HAS_INTEGER 1
@@ -704,6 +705,39 @@ prepare_index(PyArrayObject *self, PyObject *index,
/**
+ * Check if self has memory overlap with one of the index arrays, or with extra_op.
+ *
+ * @returns 1 if memory overlap found, 0 if not.
+ */
+NPY_NO_EXPORT int
+index_has_memory_overlap(PyArrayObject *self,
+ int index_type, npy_index_info *indices, int num,
+ PyObject *extra_op)
+{
+ int i;
+
+ if (index_type & (HAS_FANCY | HAS_BOOL)) {
+ for (i = 0; i < num; ++i) {
+ if (indices[i].object != NULL &&
+ PyArray_Check(indices[i].object) &&
+ solve_may_share_memory(self,
+ (PyArrayObject *)indices[i].object,
+ 1) != 0) {
+ return 1;
+ }
+ }
+ }
+
+ if (extra_op != NULL && PyArray_Check(extra_op) &&
+ solve_may_share_memory(self, (PyArrayObject *)extra_op, 1) != 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
* Get pointer for an integer index.
*
* For a purely integer index, set ptr to the memory address.
@@ -1923,7 +1957,9 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op)
* Either they are equivalent, or the values must
* be a scalar
*/
- (PyArray_EQUIVALENTLY_ITERABLE(ind, tmp_arr) ||
+ (PyArray_EQUIVALENTLY_ITERABLE(ind, tmp_arr,
+ PyArray_TRIVIALLY_ITERABLE_OP_READ,
+ PyArray_TRIVIALLY_ITERABLE_OP_READ) ||
(PyArray_NDIM(tmp_arr) == 0 &&
PyArray_TRIVIALLY_ITERABLE(tmp_arr))) &&
/* Check if the type is equivalent to INTP */
@@ -3130,19 +3166,22 @@ PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type,
/*NUMPY_API
*
- * Use advanced indexing to iterate an array. Please note
- * that most of this public API is currently not guaranteed
- * to stay the same between versions. If you plan on using
- * it, please consider adding more utility functions here
- * to accommodate new features.
+ * Same as PyArray_MapIterArray, but:
+ *
+ * If copy_if_overlap != 0, check if `a` has memory overlap with any of the
+ * arrays in `index` and with `extra_op`. If yes, make copies as appropriate
+ * to avoid problems if `a` is modified during the iteration.
+ * `iter->array` may contain a copied array (with UPDATEIFCOPY set).
*/
NPY_NO_EXPORT PyObject *
-PyArray_MapIterArray(PyArrayObject * a, PyObject * index)
+PyArray_MapIterArrayCopyIfOverlap(PyArrayObject * a, PyObject * index,
+ int copy_if_overlap, PyArrayObject *extra_op)
{
PyArrayMapIterObject * mit = NULL;
PyArrayObject *subspace = NULL;
npy_index_info indices[NPY_MAXDIMS * 2 + 1];
int i, index_num, ndim, fancy_ndim, index_type;
+ PyArrayObject *a_copy = NULL;
index_type = prepare_index(a, index, indices, &index_num,
&ndim, &fancy_ndim, 0);
@@ -3151,6 +3190,28 @@ PyArray_MapIterArray(PyArrayObject * a, PyObject * index)
return NULL;
}
+ if (copy_if_overlap && index_has_memory_overlap(a, index_type, indices,
+ index_num,
+ (PyObject *)extra_op)) {
+ /* Make a copy of the input array */
+ a_copy = (PyArrayObject *)PyArray_NewLikeArray(a, NPY_ANYORDER,
+ NULL, 0);
+ if (a_copy == NULL) {
+ goto fail;
+ }
+
+ if (PyArray_CopyInto(a_copy, a) != 0) {
+ goto fail;
+ }
+
+ Py_INCREF(a);
+ if (PyArray_SetUpdateIfCopyBase(a_copy, a) < 0) {
+ goto fail;
+ }
+
+ a = a_copy;
+ }
+
/* If it is not a pure fancy index, need to get the subspace */
if (index_type != HAS_FANCY) {
if (get_view_from_index(a, &subspace, indices, index_num, 1) < 0) {
@@ -3178,6 +3239,7 @@ PyArray_MapIterArray(PyArrayObject * a, PyObject * index)
goto fail;
}
+ Py_XDECREF(a_copy);
Py_XDECREF(subspace);
PyArray_MapIterReset(mit);
@@ -3188,6 +3250,7 @@ PyArray_MapIterArray(PyArrayObject * a, PyObject * index)
return (PyObject *)mit;
fail:
+ Py_XDECREF(a_copy);
Py_XDECREF(subspace);
Py_XDECREF((PyObject *)mit);
for (i=0; i < index_num; i++) {
@@ -3197,6 +3260,17 @@ PyArray_MapIterArray(PyArrayObject * a, PyObject * index)
}
+/*NUMPY_API
+ *
+ * Use advanced indexing to iterate an array.
+ */
+NPY_NO_EXPORT PyObject *
+PyArray_MapIterArray(PyArrayObject * a, PyObject * index)
+{
+ return PyArray_MapIterArrayCopyIfOverlap(a, index, 0, NULL);
+}
+
+
#undef HAS_INTEGER
#undef HAS_NEWAXIS
#undef HAS_SLICE
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index becd04370..f00de46c4 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -753,12 +753,17 @@ PyArray_CanCoerceScalar(int thistype, int neededtype,
/*
* Make a new empty array, of the passed size, of a type that takes the
* priority of ap1 and ap2 into account.
+ *
+ * If `out` is non-NULL, memory overlap is checked with ap1 and ap2, and an
+ * updateifcopy temporary array may be returned. If `result` is non-NULL, the
+ * output array to be returned (`out` if non-NULL and the newly allocated array
+ * otherwise) is incref'd and put to *result.
*/
static PyArrayObject *
new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
- int nd, npy_intp dimensions[], int typenum)
+ int nd, npy_intp dimensions[], int typenum, PyArrayObject **result)
{
- PyArrayObject *ret;
+ PyArrayObject *out_buf;
PyTypeObject *subtype;
double prior1, prior2;
/*
@@ -776,6 +781,7 @@ new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
}
if (out) {
int d;
+
/* verify that out is usable */
if (Py_TYPE(out) != subtype ||
PyArray_NDIM(out) != nd ||
@@ -793,15 +799,49 @@ new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
return 0;
}
}
- Py_INCREF(out);
- return out;
+
+ /* check for memory overlap */
+ if (!(solve_may_share_memory(out, ap1, 1) == 0 &&
+ solve_may_share_memory(out, ap2, 1) == 0)) {
+ /* allocate temporary output array */
+ out_buf = (PyArrayObject *)PyArray_NewLikeArray(out, NPY_CORDER,
+ NULL, 0);
+ if (out_buf == NULL) {
+ return NULL;
+ }
+
+ /* set copy-back */
+ Py_INCREF(out);
+ if (PyArray_SetUpdateIfCopyBase(out_buf, out) < 0) {
+ Py_DECREF(out);
+ Py_DECREF(out_buf);
+ return NULL;
+ }
+ }
+ else {
+ Py_INCREF(out);
+ out_buf = out;
+ }
+
+ if (result) {
+ Py_INCREF(out);
+ *result = out;
+ }
+
+ return out_buf;
}
- ret = (PyArrayObject *)PyArray_New(subtype, nd, dimensions,
- typenum, NULL, NULL, 0, 0,
- (PyObject *)
- (prior2 > prior1 ? ap2 : ap1));
- return ret;
+ out_buf = (PyArrayObject *)PyArray_New(subtype, nd, dimensions,
+ typenum, NULL, NULL, 0, 0,
+ (PyObject *)
+ (prior2 > prior1 ? ap2 : ap1));
+
+ if (out_buf != NULL && result) {
+ Py_INCREF(out_buf);
+ *result = out_buf;
+ }
+
+ return out_buf;
}
/* Could perhaps be redone to not make contiguous arrays */
@@ -897,7 +937,7 @@ PyArray_MatrixProduct(PyObject *op1, PyObject *op2)
NPY_NO_EXPORT PyObject *
PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
{
- PyArrayObject *ap1, *ap2, *ret = NULL;
+ PyArrayObject *ap1, *ap2, *out_buf = NULL, *result = NULL;
PyArrayIterObject *it1, *it2;
npy_intp i, j, l;
int typenum, nd, axis, matchDim;
@@ -939,12 +979,12 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
#endif
if (PyArray_NDIM(ap1) == 0 || PyArray_NDIM(ap2) == 0) {
- ret = (PyArray_NDIM(ap1) == 0 ? ap1 : ap2);
- ret = (PyArrayObject *)Py_TYPE(ret)->tp_as_number->nb_multiply(
+ result = (PyArray_NDIM(ap1) == 0 ? ap1 : ap2);
+ result = (PyArrayObject *)Py_TYPE(result)->tp_as_number->nb_multiply(
(PyObject *)ap1, (PyObject *)ap2);
Py_DECREF(ap1);
Py_DECREF(ap2);
- return (PyObject *)ret;
+ return (PyObject *)result;
}
l = PyArray_DIMS(ap1)[PyArray_NDIM(ap1) - 1];
if (PyArray_NDIM(ap2) > 1) {
@@ -976,24 +1016,24 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
is1 = PyArray_STRIDES(ap1)[PyArray_NDIM(ap1)-1];
is2 = PyArray_STRIDES(ap2)[matchDim];
/* Choose which subtype to return */
- ret = new_array_for_sum(ap1, ap2, out, nd, dimensions, typenum);
- if (ret == NULL) {
+ out_buf = new_array_for_sum(ap1, ap2, out, nd, dimensions, typenum, &result);
+ if (out_buf == NULL) {
goto fail;
}
/* Ensure that multiarray.dot(<Nx0>,<0xM>) -> zeros((N,M)) */
if (PyArray_SIZE(ap1) == 0 && PyArray_SIZE(ap2) == 0) {
- memset(PyArray_DATA(ret), 0, PyArray_NBYTES(ret));
+ memset(PyArray_DATA(out_buf), 0, PyArray_NBYTES(out_buf));
}
- dot = PyArray_DESCR(ret)->f->dotfunc;
+ dot = PyArray_DESCR(out_buf)->f->dotfunc;
if (dot == NULL) {
PyErr_SetString(PyExc_ValueError,
"dot not available for this type");
goto fail;
}
- op = PyArray_DATA(ret);
- os = PyArray_DESCR(ret)->elsize;
+ op = PyArray_DATA(out_buf);
+ os = PyArray_DESCR(out_buf)->elsize;
axis = PyArray_NDIM(ap1)-1;
it1 = (PyArrayIterObject *)
PyArray_IterAllButAxis((PyObject *)ap1, &axis);
@@ -1009,7 +1049,7 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(ap2));
while (it1->index < it1->size) {
while (it2->index < it2->size) {
- dot(it1->dataptr, is1, it2->dataptr, is2, op, l, ret);
+ dot(it1->dataptr, is1, it2->dataptr, is2, op, l, out_buf);
op += os;
PyArray_ITER_NEXT(it2);
}
@@ -1025,12 +1065,17 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
}
Py_DECREF(ap1);
Py_DECREF(ap2);
- return (PyObject *)ret;
+
+ /* Trigger possible copy-back into `result` */
+ Py_DECREF(out_buf);
+
+ return (PyObject *)result;
fail:
Py_XDECREF(ap1);
Py_XDECREF(ap2);
- Py_XDECREF(ret);
+ Py_XDECREF(out_buf);
+ Py_XDECREF(result);
return NULL;
}
@@ -1142,7 +1187,7 @@ _pyarray_correlate(PyArrayObject *ap1, PyArrayObject *ap2, int typenum,
* Need to choose an output array that can hold a sum
* -- use priority to determine which subtype.
*/
- ret = new_array_for_sum(ap1, ap2, NULL, 1, &length, typenum);
+ ret = new_array_for_sum(ap1, ap2, NULL, 1, &length, typenum, NULL);
if (ret == NULL) {
return NULL;
}
@@ -1465,8 +1510,8 @@ PyArray_EquivTypes(PyArray_Descr *type1, PyArray_Descr *type2)
&& _equivalent_fields(type1->fields, type2->fields));
}
if (type_num1 == NPY_DATETIME
- || type_num1 == NPY_DATETIME
- || type_num2 == NPY_TIMEDELTA
+ || type_num1 == NPY_TIMEDELTA
+ || type_num2 == NPY_DATETIME
|| type_num2 == NPY_TIMEDELTA) {
return ((type_num1 == type_num2)
&& has_equivalent_datetime_metadata(type1, type2));
@@ -2240,7 +2285,7 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args)
}
/* array scalar output */
- ret = new_array_for_sum(ap1, ap2, NULL, 0, (npy_intp *)NULL, typenum);
+ ret = new_array_for_sum(ap1, ap2, NULL, 0, (npy_intp *)NULL, typenum, NULL);
if (ret == NULL) {
goto fail;
}
diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c
index 48f4928db..b74aca01c 100644
--- a/numpy/core/src/multiarray/nditer_constr.c
+++ b/numpy/core/src/multiarray/nditer_constr.c
@@ -17,6 +17,8 @@
#include "arrayobject.h"
#include "templ_common.h"
+#include "mem_overlap.h"
+
/* Internal helper functions private to this file */
static int
@@ -2708,6 +2710,93 @@ npyiter_allocate_arrays(NpyIter *iter,
bufferdata = NIT_BUFFERDATA(iter);
}
+ if (flags & NPY_ITER_COPY_IF_OVERLAP) {
+ /*
+ * Perform operand memory overlap checks, if requested.
+ *
+ * If any write operand has memory overlap with any read operand,
+ * eliminate all overlap by making temporary copies, by enabling
+ * NPY_OP_ITFLAG_FORCECOPY for the write operand to force UPDATEIFCOPY.
+ *
+ * Operands with NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE enabled are not
+ * considered overlapping if the arrays are exactly the same. In this
+ * case, the iterator loops through them in the same order element by
+ * element. (As usual, the user-provided inner loop is assumed to be
+ * able to deal with this level of simple aliasing.)
+ */
+ for (iop = 0; iop < nop; ++iop) {
+ int may_share_memory = 0;
+ int iother;
+
+ if (op[iop] == NULL) {
+ /* Iterator will always allocate */
+ continue;
+ }
+
+ if (!(op_itflags[iop] & NPY_OP_ITFLAG_WRITE)) {
+ /*
+ * Copy output operands only, not inputs.
+ * A more sophisticated heuristic could be
+ * substituted here later.
+ */
+ continue;
+ }
+
+ for (iother = 0; iother < nop; ++iother) {
+ if (iother == iop || op[iother] == NULL) {
+ continue;
+ }
+
+ if (!(op_itflags[iother] & NPY_OP_ITFLAG_READ)) {
+ /* No data dependence for arrays not read from */
+ continue;
+ }
+
+ if (op_itflags[iother] & NPY_OP_ITFLAG_FORCECOPY) {
+ /* Already copied */
+ continue;
+ }
+
+ /*
+ * If the arrays are views to exactly the same data, no need
+ * to make copies, if the caller (eg ufunc) says it accesses
+ * data only in the iterator order.
+ *
+ * However, if there is internal overlap (e.g. a zero stride on
+ * a non-unit dimension), a copy cannot be avoided.
+ */
+ if ((op_flags[iop] & NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE) &&
+ (op_flags[iother] & NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE) &&
+ PyArray_BYTES(op[iop]) == PyArray_BYTES(op[iother]) &&
+ PyArray_NDIM(op[iop]) == PyArray_NDIM(op[iother]) &&
+ PyArray_CompareLists(PyArray_DIMS(op[iop]),
+ PyArray_DIMS(op[iother]),
+ PyArray_NDIM(op[iop])) &&
+ PyArray_CompareLists(PyArray_STRIDES(op[iop]),
+ PyArray_STRIDES(op[iother]),
+ PyArray_NDIM(op[iop])) &&
+ PyArray_DESCR(op[iop]) == PyArray_DESCR(op[iother]) &&
+ solve_may_have_internal_overlap(op[iop], 1) == 0) {
+
+ continue;
+ }
+
+ /*
+ * Use max work = 1. If the arrays are large, it might
+ * make sense to go further.
+ */
+ may_share_memory = solve_may_share_memory(op[iop],
+ op[iother],
+ 1);
+
+ if (may_share_memory) {
+ op_itflags[iop] |= NPY_OP_ITFLAG_FORCECOPY;
+ break;
+ }
+ }
+ }
+ }
+
for (iop = 0; iop < nop; ++iop) {
/*
* Check whether there are any WRITEMASKED REDUCE operands
@@ -2797,9 +2886,15 @@ npyiter_allocate_arrays(NpyIter *iter,
NBF_STRIDES(bufferdata)[iop] = 0;
}
}
- /* If casting is required and permitted */
- else if ((op_itflags[iop] & NPY_OP_ITFLAG_CAST) &&
- (op_flags[iop] & (NPY_ITER_COPY|NPY_ITER_UPDATEIFCOPY))) {
+ /*
+ * Make a temporary copy if,
+ * 1. If casting is required and permitted, or,
+ * 2. If force-copy is requested
+ */
+ else if (((op_itflags[iop] & NPY_OP_ITFLAG_CAST) &&
+ (op_flags[iop] &
+ (NPY_ITER_COPY|NPY_ITER_UPDATEIFCOPY))) ||
+ (op_itflags[iop] & NPY_OP_ITFLAG_FORCECOPY)) {
PyArrayObject *temp;
int ondim = PyArray_NDIM(op[iop]);
diff --git a/numpy/core/src/multiarray/nditer_impl.h b/numpy/core/src/multiarray/nditer_impl.h
index ae24f46e6..7788d327b 100644
--- a/numpy/core/src/multiarray/nditer_impl.h
+++ b/numpy/core/src/multiarray/nditer_impl.h
@@ -122,6 +122,8 @@
#define NPY_OP_ITFLAG_WRITEMASKED 0x0080
/* The operand's data pointer is pointing into its buffer */
#define NPY_OP_ITFLAG_USINGBUFFER 0x0100
+/* The operand must be copied (with UPDATEIFCOPY if also ITFLAG_WRITE) */
+#define NPY_OP_ITFLAG_FORCECOPY 0x0200
/*
* The data layout of the iterator is fully specified by
diff --git a/numpy/core/src/multiarray/nditer_pywrap.c b/numpy/core/src/multiarray/nditer_pywrap.c
index c735e7ad1..5f921fda0 100644
--- a/numpy/core/src/multiarray/nditer_pywrap.c
+++ b/numpy/core/src/multiarray/nditer_pywrap.c
@@ -148,6 +148,11 @@ NpyIter_GlobalFlagsConverter(PyObject *flags_in, npy_uint32 *flags)
flag = NPY_ITER_C_INDEX;
}
break;
+ case 'i':
+ if (strcmp(str, "copy_if_overlap") == 0) {
+ flag = NPY_ITER_COPY_IF_OVERLAP;
+ }
+ break;
case 'n':
if (strcmp(str, "common_dtype") == 0) {
flag = NPY_ITER_COMMON_DTYPE;
@@ -355,6 +360,11 @@ NpyIter_OpFlagsConverter(PyObject *op_flags_in,
break;
}
break;
+ case 'o':
+ if (strcmp(str, "overlap_assume_elementwise") == 0) {
+ flag = NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE;
+ }
+ break;
case 'r':
if (length > 4) switch (str[4]) {
case 'o':
@@ -2416,9 +2426,9 @@ NPY_NO_EXPORT PySequenceMethods npyiter_as_sequence = {
(binaryfunc)NULL, /*sq_concat*/
(ssizeargfunc)NULL, /*sq_repeat*/
(ssizeargfunc)npyiter_seq_item, /*sq_item*/
- (ssizessizeargfunc)npyiter_seq_slice, /*sq_slice*/
+ (ssizessizeargfunc)NULL, /*sq_slice*/
(ssizeobjargproc)npyiter_seq_ass_item, /*sq_ass_item*/
- (ssizessizeobjargproc)npyiter_seq_ass_slice,/*sq_ass_slice*/
+ (ssizessizeobjargproc)NULL, /*sq_ass_slice*/
(objobjproc)NULL, /*sq_contains */
(binaryfunc)NULL, /*sq_inplace_concat */
(ssizeargfunc)NULL, /*sq_inplace_repeat */
diff --git a/numpy/core/src/multiarray/sequence.c b/numpy/core/src/multiarray/sequence.c
index 520732acf..55b72c198 100644
--- a/numpy/core/src/multiarray/sequence.c
+++ b/numpy/core/src/multiarray/sequence.c
@@ -27,90 +27,6 @@ array_any_nonzero(PyArrayObject *mp);
we fill it in here so that PySequence_XXXX calls work as expected
*/
-
-static PyObject *
-array_slice(PyArrayObject *self, Py_ssize_t ilow, Py_ssize_t ihigh)
-{
- PyArrayObject *ret;
- PyArray_Descr *dtype;
- Py_ssize_t dim0;
- char *data;
- npy_intp shape[NPY_MAXDIMS];
-
- if (PyArray_NDIM(self) == 0) {
- PyErr_SetString(PyExc_ValueError, "cannot slice a 0-d array");
- return NULL;
- }
-
- dim0 = PyArray_DIM(self, 0);
- if (ilow < 0) {
- ilow = 0;
- }
- else if (ilow > dim0) {
- ilow = dim0;
- }
- if (ihigh < ilow) {
- ihigh = ilow;
- }
- else if (ihigh > dim0) {
- ihigh = dim0;
- }
-
- data = PyArray_DATA(self);
- if (ilow < ihigh) {
- data += ilow * PyArray_STRIDE(self, 0);
- }
-
- /* Same shape except dimension 0 */
- shape[0] = ihigh - ilow;
- memcpy(shape+1, PyArray_DIMS(self) + 1,
- (PyArray_NDIM(self)-1)*sizeof(npy_intp));
-
- dtype = PyArray_DESCR(self);
- Py_INCREF(dtype);
- ret = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(self), dtype,
- PyArray_NDIM(self), shape,
- PyArray_STRIDES(self), data,
- PyArray_FLAGS(self),
- (PyObject *)self);
- if (ret == NULL) {
- return NULL;
- }
- Py_INCREF(self);
- if (PyArray_SetBaseObject(ret, (PyObject *)self) < 0) {
- Py_DECREF(ret);
- return NULL;
- }
- PyArray_UpdateFlags(ret, NPY_ARRAY_UPDATE_ALL);
-
- return (PyObject *)ret;
-}
-
-
-static int
-array_assign_slice(PyArrayObject *self, Py_ssize_t ilow,
- Py_ssize_t ihigh, PyObject *v) {
- int ret;
- PyArrayObject *tmp;
-
- if (v == NULL) {
- PyErr_SetString(PyExc_ValueError,
- "cannot delete array elements");
- return -1;
- }
- if (PyArray_FailUnlessWriteable(self, "assignment destination") < 0) {
- return -1;
- }
- tmp = (PyArrayObject *)array_slice(self, ilow, ihigh);
- if (tmp == NULL) {
- return -1;
- }
- ret = PyArray_CopyObject(tmp, v);
- Py_DECREF(tmp);
-
- return ret;
-}
-
static int
array_contains(PyArrayObject *self, PyObject *el)
{
@@ -134,9 +50,9 @@ NPY_NO_EXPORT PySequenceMethods array_as_sequence = {
(binaryfunc)NULL, /*sq_concat is handled by nb_add*/
(ssizeargfunc)NULL,
(ssizeargfunc)array_item,
- (ssizessizeargfunc)array_slice,
- (ssizeobjargproc)array_assign_item, /*sq_ass_item*/
- (ssizessizeobjargproc)array_assign_slice, /*sq_ass_slice*/
+ (ssizessizeargfunc)NULL,
+ (ssizeobjargproc)array_assign_item, /*sq_ass_item*/
+ (ssizessizeobjargproc)NULL, /*sq_ass_slice*/
(objobjproc) array_contains, /*sq_contains */
(binaryfunc) NULL, /*sg_inplace_concat */
(ssizeargfunc)NULL,
diff --git a/numpy/core/src/private/lowlevel_strided_loops.h b/numpy/core/src/private/lowlevel_strided_loops.h
index 02b8c73c1..f66de14b5 100644
--- a/numpy/core/src/private/lowlevel_strided_loops.h
+++ b/numpy/core/src/private/lowlevel_strided_loops.h
@@ -2,6 +2,7 @@
#define __LOWLEVEL_STRIDED_LOOPS_H
#include "common.h"
#include <npy_config.h>
+#include "mem_overlap.h"
/*
* NOTE: This API should remain private for the time being, to allow
@@ -662,7 +663,24 @@ npy_bswap8_unaligned(char * x)
* Note: Equivalently iterable macro requires one of arr1 or arr2 be
* trivially iterable to be valid.
*/
-#define PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2) ( \
+
+/**
+ * Determine whether two arrays are safe for trivial iteration in cases where
+ * some of the arrays may be modified.
+ *
+ * In-place iteration is safe if one of the following is true:
+ *
+ * - Both arrays are read-only
+ * - The arrays do not have overlapping memory (based on a check that may be too
+ * strict)
+ * - The strides match, and the non-read-only array base addresses are equal or
+ * before the read-only one, ensuring correct data dependency.
+ */
+
+#define PyArray_TRIVIALLY_ITERABLE_OP_NOREAD 0
+#define PyArray_TRIVIALLY_ITERABLE_OP_READ 1
+
+#define PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr2) ( \
PyArray_NDIM(arr1) == PyArray_NDIM(arr2) && \
PyArray_CompareLists(PyArray_DIMS(arr1), \
PyArray_DIMS(arr2), \
@@ -673,6 +691,67 @@ npy_bswap8_unaligned(char * x)
NPY_ARRAY_F_CONTIGUOUS)) \
)
+#define PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size, arr) ( \
+ size == 1 ? 0 : ((PyArray_NDIM(arr) == 1) ? \
+ PyArray_STRIDE(arr, 0) : \
+ PyArray_ITEMSIZE(arr)))
+
+static NPY_INLINE int
+PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK(PyArrayObject *arr1, PyArrayObject *arr2,
+ int arr1_read, int arr2_read)
+{
+ npy_intp size1, size2, stride1, stride2;
+ int arr1_ahead = 0, arr2_ahead = 0;
+
+ if (arr1_read && arr2_read) {
+ return 1;
+ }
+
+ if (solve_may_share_memory(arr1, arr2, 1) == 0) {
+ return 1;
+ }
+
+ /*
+ * Arrays overlapping in memory may be equivalently iterable if input
+ * arrays stride ahead faster than output arrays.
+ */
+
+ size1 = PyArray_SIZE(arr1);
+ size2 = PyArray_SIZE(arr2);
+
+ stride1 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size1, arr1);
+ stride2 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size2, arr2);
+
+ /*
+ * Arrays with zero stride are never "ahead" since the element is reused
+ * (at this point we know the array extents overlap).
+ */
+
+ if (stride1 > 0) {
+ arr1_ahead = (stride1 >= stride2 &&
+ PyArray_BYTES(arr1) >= PyArray_BYTES(arr2));
+ }
+ else if (stride1 < 0) {
+ arr1_ahead = (stride1 <= stride2 &&
+ PyArray_BYTES(arr1) <= PyArray_BYTES(arr2));
+ }
+
+ if (stride2 > 0) {
+ arr2_ahead = (stride2 >= stride1 &&
+ PyArray_BYTES(arr2) >= PyArray_BYTES(arr1));
+ }
+ else if (stride2 < 0) {
+ arr2_ahead = (stride2 <= stride1 &&
+ PyArray_BYTES(arr2) <= PyArray_BYTES(arr1));
+ }
+
+ return (!arr1_read || arr1_ahead) && (!arr2_read || arr2_ahead);
+}
+
+#define PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2, arr1_read, arr2_read) ( \
+ PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr2) && \
+ PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK( \
+ arr1, arr2, arr1_read, arr2_read))
#define PyArray_TRIVIALLY_ITERABLE(arr) ( \
PyArray_NDIM(arr) <= 1 || \
PyArray_CHKFLAGS(arr, NPY_ARRAY_C_CONTIGUOUS) || \
@@ -687,15 +766,16 @@ npy_bswap8_unaligned(char * x)
PyArray_ITEMSIZE(arr)));
-#define PyArray_TRIVIALLY_ITERABLE_PAIR(arr1, arr2) (\
+#define PyArray_TRIVIALLY_ITERABLE_PAIR(arr1, arr2, arr1_read, arr2_read) ( \
PyArray_TRIVIALLY_ITERABLE(arr1) && \
(PyArray_NDIM(arr2) == 0 || \
- PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2) || \
+ PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr2) || \
(PyArray_NDIM(arr1) == 0 && \
PyArray_TRIVIALLY_ITERABLE(arr2) \
) \
- ) \
- )
+ ) && \
+ PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK(arr1, arr2, arr1_read, arr2_read) \
+ )
#define PyArray_PREPARE_TRIVIAL_PAIR_ITERATION(arr1, arr2, \
count, \
data1, data2, \
@@ -705,33 +785,32 @@ npy_bswap8_unaligned(char * x)
count = ((size1 > size2) || size1 == 0) ? size1 : size2; \
data1 = PyArray_BYTES(arr1); \
data2 = PyArray_BYTES(arr2); \
- stride1 = (size1 == 1 ? 0 : ((PyArray_NDIM(arr1) == 1) ? \
- PyArray_STRIDE(arr1, 0) : \
- PyArray_ITEMSIZE(arr1))); \
- stride2 = (size2 == 1 ? 0 : ((PyArray_NDIM(arr2) == 1) ? \
- PyArray_STRIDE(arr2, 0) : \
- PyArray_ITEMSIZE(arr2))); \
+ stride1 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size1, arr1); \
+ stride2 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size2, arr2); \
}
-#define PyArray_TRIVIALLY_ITERABLE_TRIPLE(arr1, arr2, arr3) (\
+#define PyArray_TRIVIALLY_ITERABLE_TRIPLE(arr1, arr2, arr3, arr1_read, arr2_read, arr3_read) ( \
PyArray_TRIVIALLY_ITERABLE(arr1) && \
((PyArray_NDIM(arr2) == 0 && \
(PyArray_NDIM(arr3) == 0 || \
- PyArray_EQUIVALENTLY_ITERABLE(arr1, arr3) \
+ PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr3) \
) \
) || \
- (PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2) && \
+ (PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr2) && \
(PyArray_NDIM(arr3) == 0 || \
- PyArray_EQUIVALENTLY_ITERABLE(arr1, arr3) \
+ PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr3) \
) \
) || \
(PyArray_NDIM(arr1) == 0 && \
PyArray_TRIVIALLY_ITERABLE(arr2) && \
(PyArray_NDIM(arr3) == 0 || \
- PyArray_EQUIVALENTLY_ITERABLE(arr2, arr3) \
+ PyArray_EQUIVALENTLY_ITERABLE_BASE(arr2, arr3) \
) \
) \
- ) \
+ ) && \
+ PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK(arr1, arr2, arr1_read, arr2_read) && \
+ PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK(arr1, arr3, arr1_read, arr3_read) && \
+ PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK(arr2, arr3, arr2_read, arr3_read) \
)
#define PyArray_PREPARE_TRIVIAL_TRIPLE_ITERATION(arr1, arr2, arr3, \
@@ -746,15 +825,9 @@ npy_bswap8_unaligned(char * x)
data1 = PyArray_BYTES(arr1); \
data2 = PyArray_BYTES(arr2); \
data3 = PyArray_BYTES(arr3); \
- stride1 = (size1 == 1 ? 0 : ((PyArray_NDIM(arr1) == 1) ? \
- PyArray_STRIDE(arr1, 0) : \
- PyArray_ITEMSIZE(arr1))); \
- stride2 = (size2 == 1 ? 0 : ((PyArray_NDIM(arr2) == 1) ? \
- PyArray_STRIDE(arr2, 0) : \
- PyArray_ITEMSIZE(arr2))); \
- stride3 = (size3 == 1 ? 0 : ((PyArray_NDIM(arr3) == 1) ? \
- PyArray_STRIDE(arr3, 0) : \
- PyArray_ITEMSIZE(arr3))); \
+ stride1 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size1, arr1); \
+ stride2 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size2, arr2); \
+ stride3 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size3, arr3); \
}
#endif
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index f76ae388b..86c9d494b 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -1226,7 +1226,7 @@ NPY_NO_EXPORT void
const @type@ in2 = *(@type@ *)ip2;
*((npy_bool *)op1) = in1 != in2;
- if (in1 == NPY_DATETIME_NAT && in1 == NPY_DATETIME_NAT) {
+ if (in1 == NPY_DATETIME_NAT && in2 == NPY_DATETIME_NAT) {
NPY_ALLOW_C_API_DEF
NPY_ALLOW_C_API;
/* 2016-01-18, 1.11 */
diff --git a/numpy/core/src/umath/reduction.c b/numpy/core/src/umath/reduction.c
index 8079f7e0f..47598bed9 100644
--- a/numpy/core/src/umath/reduction.c
+++ b/numpy/core/src/umath/reduction.c
@@ -83,7 +83,8 @@ allocate_reduce_result(PyArrayObject *arr, npy_bool *axis_flags,
*/
static PyArrayObject *
conform_reduce_result(int ndim, npy_bool *axis_flags,
- PyArrayObject *out, int keepdims, const char *funcname)
+ PyArrayObject *out, int keepdims, const char *funcname,
+ int need_copy)
{
npy_intp strides[NPY_MAXDIMS], shape[NPY_MAXDIMS];
npy_intp *strides_out = PyArray_STRIDES(out);
@@ -151,6 +152,7 @@ conform_reduce_result(int ndim, npy_bool *axis_flags,
/* Allocate the view */
dtype = PyArray_DESCR(out);
Py_INCREF(dtype);
+
ret = (PyArrayObject_fields *)PyArray_NewFromDescr(&PyArray_Type,
dtype,
ndim, shape,
@@ -161,13 +163,41 @@ conform_reduce_result(int ndim, npy_bool *axis_flags,
if (ret == NULL) {
return NULL;
}
+
Py_INCREF(out);
if (PyArray_SetBaseObject((PyArrayObject *)ret, (PyObject *)out) < 0) {
Py_DECREF(ret);
return NULL;
}
- return (PyArrayObject *)ret;
+ if (need_copy) {
+ PyArrayObject *ret_copy;
+
+ ret_copy = (PyArrayObject *)PyArray_NewLikeArray(
+ (PyArrayObject *)ret, NPY_ANYORDER, NULL, 0);
+ if (ret_copy == NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+
+ if (PyArray_CopyInto(ret_copy, (PyArrayObject *)ret) != 0) {
+ Py_DECREF(ret);
+ Py_DECREF(ret_copy);
+ return NULL;
+ }
+
+ Py_INCREF(ret);
+ if (PyArray_SetUpdateIfCopyBase(ret_copy, (PyArrayObject *)ret) < 0) {
+ Py_DECREF(ret);
+ Py_DECREF(ret_copy);
+ return NULL;
+ }
+
+ return ret_copy;
+ }
+ else {
+ return (PyArrayObject *)ret;
+ }
}
/*
@@ -201,11 +231,16 @@ PyArray_CreateReduceResult(PyArrayObject *operand, PyArrayObject *out,
result = allocate_reduce_result(operand, axis_flags, dtype, subok);
}
else {
+ int need_copy = 0;
+
+ if (solve_may_share_memory(operand, out, 1) != 0) {
+ need_copy = 1;
+ }
+
/* Steal the dtype reference */
Py_XDECREF(dtype);
-
result = conform_reduce_result(PyArray_NDIM(operand), axis_flags,
- out, keepdims, funcname);
+ out, keepdims, funcname, need_copy);
}
return result;
@@ -445,6 +480,9 @@ PyUFunc_ReduceWrapper(PyArrayObject *operand, PyArrayObject *out,
/*
* This either conforms 'out' to the ndim of 'operand', or allocates
* a new array appropriate for this reduction.
+ *
+ * A new array with UPDATEIFCOPY is allocated if operand and out have memory
+ * overlap.
*/
Py_INCREF(result_dtype);
result = PyArray_CreateReduceResult(operand, out,
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 62024d2e3..0bae2d591 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -41,6 +41,7 @@
#include "lowlevel_strided_loops.h"
#include "ufunc_type_resolution.h"
#include "reduction.h"
+#include "mem_overlap.h"
#include "ufunc_object.h"
#include "ufunc_override.h"
@@ -1416,7 +1417,8 @@ iterator_loop(PyUFuncObject *ufunc,
/* Set up the flags */
for (i = 0; i < nin; ++i) {
op_flags[i] = NPY_ITER_READONLY |
- NPY_ITER_ALIGNED;
+ NPY_ITER_ALIGNED |
+ NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE;
/*
* If READWRITE flag has been set for this operand,
* then clear default READONLY flag
@@ -1431,7 +1433,8 @@ iterator_loop(PyUFuncObject *ufunc,
NPY_ITER_ALIGNED |
NPY_ITER_ALLOCATE |
NPY_ITER_NO_BROADCAST |
- NPY_ITER_NO_SUBTYPE;
+ NPY_ITER_NO_SUBTYPE |
+ NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE;
}
iter_flags = ufunc->iter_flags |
@@ -1440,7 +1443,22 @@ iterator_loop(PyUFuncObject *ufunc,
NPY_ITER_ZEROSIZE_OK |
NPY_ITER_BUFFERED |
NPY_ITER_GROWINNER |
- NPY_ITER_DELAY_BUFALLOC;
+ NPY_ITER_DELAY_BUFALLOC |
+ NPY_ITER_COPY_IF_OVERLAP;
+
+ /* Call the __array_prepare__ functions for already existing output arrays.
+ * Do this before creating the iterator, as the iterator may UPDATEIFCOPY
+ * some of them.
+ */
+ for (i = 0; i < nout; ++i) {
+ if (op[nin+i] == NULL) {
+ continue;
+ }
+ if (prepare_ufunc_output(ufunc, &op[nin+i],
+ arr_prep[i], arr_prep_args, i) < 0) {
+ return -1;
+ }
+ }
/*
* Allocate the iterator. Because the types of the inputs
@@ -1458,32 +1476,41 @@ iterator_loop(PyUFuncObject *ufunc,
/* Copy any allocated outputs */
op_it = NpyIter_GetOperandArray(iter);
- for (i = nin; i < nop; ++i) {
- if (op[i] == NULL) {
- op[i] = op_it[i];
- Py_INCREF(op[i]);
- }
- }
-
- /* Call the __array_prepare__ functions where necessary */
for (i = 0; i < nout; ++i) {
- if (prepare_ufunc_output(ufunc, &op[nin+i],
- arr_prep[i], arr_prep_args, i) < 0) {
- NpyIter_Deallocate(iter);
- return -1;
+ if (op[nin+i] == NULL) {
+ op[nin+i] = op_it[nin+i];
+ Py_INCREF(op[nin+i]);
+
+ /* Call the __array_prepare__ functions for the new array */
+ if (prepare_ufunc_output(ufunc, &op[nin+i],
+ arr_prep[i], arr_prep_args, i) < 0) {
+ NpyIter_Deallocate(iter);
+ return -1;
+ }
+
+ /*
+ * In case __array_prepare__ returned a different array, put the
+ * results directly there, ignoring the array allocated by the
+ * iterator.
+ *
+ * Here, we assume the user-provided __array_prepare__ behaves
+ * sensibly and doesn't return an array overlapping in memory
+ * with other operands --- the op[nin+i] array passed to it is newly
+ * allocated and doesn't have any overlap.
+ */
+ baseptrs[nin+i] = PyArray_BYTES(op[nin+i]);
+ }
+ else {
+ baseptrs[nin+i] = PyArray_BYTES(op_it[nin+i]);
}
}
/* Only do the loop if the iteration size is non-zero */
if (NpyIter_GetIterSize(iter) != 0) {
-
- /* Reset the iterator with the base pointers from the wrapped outputs */
+ /* Reset the iterator with the base pointers from possible __array_prepare__ */
for (i = 0; i < nin; ++i) {
baseptrs[i] = PyArray_BYTES(op_it[i]);
}
- for (i = nin; i < nop; ++i) {
- baseptrs[i] = PyArray_BYTES(op[i]);
- }
if (NpyIter_ResetBasePointers(iter, baseptrs, NULL) != NPY_SUCCEED) {
NpyIter_Deallocate(iter);
return -1;
@@ -1581,7 +1608,9 @@ execute_legacy_ufunc_loop(PyUFuncObject *ufunc,
}
else if (op[1] != NULL &&
PyArray_NDIM(op[1]) >= PyArray_NDIM(op[0]) &&
- PyArray_TRIVIALLY_ITERABLE_PAIR(op[0], op[1])) {
+ PyArray_TRIVIALLY_ITERABLE_PAIR(op[0], op[1],
+ PyArray_TRIVIALLY_ITERABLE_OP_READ,
+ PyArray_TRIVIALLY_ITERABLE_OP_NOREAD)) {
/* Call the __prepare_array__ if necessary */
if (prepare_ufunc_output(ufunc, &op[1],
@@ -1598,7 +1627,9 @@ execute_legacy_ufunc_loop(PyUFuncObject *ufunc,
else if (nin == 2 && nout == 1) {
if (op[2] == NULL &&
(order == NPY_ANYORDER || order == NPY_KEEPORDER) &&
- PyArray_TRIVIALLY_ITERABLE_PAIR(op[0], op[1])) {
+ PyArray_TRIVIALLY_ITERABLE_PAIR(op[0], op[1],
+ PyArray_TRIVIALLY_ITERABLE_OP_READ,
+ PyArray_TRIVIALLY_ITERABLE_OP_READ)) {
PyArrayObject *tmp;
/*
* Have to choose the input with more dimensions to clone, as
@@ -1637,7 +1668,10 @@ execute_legacy_ufunc_loop(PyUFuncObject *ufunc,
else if (op[2] != NULL &&
PyArray_NDIM(op[2]) >= PyArray_NDIM(op[0]) &&
PyArray_NDIM(op[2]) >= PyArray_NDIM(op[1]) &&
- PyArray_TRIVIALLY_ITERABLE_TRIPLE(op[0], op[1], op[2])) {
+ PyArray_TRIVIALLY_ITERABLE_TRIPLE(op[0], op[1], op[2],
+ PyArray_TRIVIALLY_ITERABLE_OP_READ,
+ PyArray_TRIVIALLY_ITERABLE_OP_READ,
+ PyArray_TRIVIALLY_ITERABLE_OP_NOREAD)) {
/* Call the __prepare_array__ if necessary */
if (prepare_ufunc_output(ufunc, &op[2],
@@ -1701,7 +1735,6 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
npy_intp *strides;
npy_intp *countptr;
- PyArrayObject **op_it;
npy_uint32 iter_flags;
if (wheremask != NULL) {
@@ -1719,7 +1752,8 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
for (i = 0; i < nin; ++i) {
op_flags[i] = default_op_in_flags |
NPY_ITER_READONLY |
- NPY_ITER_ALIGNED;
+ NPY_ITER_ALIGNED |
+ NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE;
/*
* If READWRITE flag has been set for this operand,
* then clear default READONLY flag
@@ -1730,12 +1764,19 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
}
}
for (i = nin; i < nop; ++i) {
+ /*
+ * We don't write to all elements, and the iterator may make
+ * UPDATEIFCOPY temporary copies. The output arrays must be considered
+ * READWRITE by the iterator, so that the elements we don't write to are
+ * copied to the possible temporary array.
+ */
op_flags[i] = default_op_out_flags |
- NPY_ITER_WRITEONLY |
+ NPY_ITER_READWRITE |
NPY_ITER_ALIGNED |
NPY_ITER_ALLOCATE |
NPY_ITER_NO_BROADCAST |
- NPY_ITER_NO_SUBTYPE;
+ NPY_ITER_NO_SUBTYPE |
+ NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE;
}
if (wheremask != NULL) {
op_flags[nop] = NPY_ITER_READONLY | NPY_ITER_ARRAYMASK;
@@ -1748,7 +1789,8 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
NPY_ITER_REFS_OK |
NPY_ITER_ZEROSIZE_OK |
NPY_ITER_BUFFERED |
- NPY_ITER_GROWINNER;
+ NPY_ITER_GROWINNER |
+ NPY_ITER_COPY_IF_OVERLAP;
/*
* Allocate the iterator. Because the types of the inputs
@@ -1768,22 +1810,37 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
needs_api = NpyIter_IterationNeedsAPI(iter);
- /* Copy any allocated outputs */
- op_it = NpyIter_GetOperandArray(iter);
+ /* Call the __array_prepare__ functions where necessary */
for (i = nin; i < nop; ++i) {
- if (op[i] == NULL) {
- op[i] = op_it[i];
- Py_INCREF(op[i]);
+ PyArrayObject *op_tmp;
+
+ /* prepare_ufunc_output may decref & replace pointer */
+ op_tmp = op[i];
+ Py_INCREF(op_tmp);
+
+ if (prepare_ufunc_output(ufunc, &op_tmp,
+ arr_prep[i], arr_prep_args, i) < 0) {
+ NpyIter_Deallocate(iter);
+ return -1;
}
- }
- /* Call the __array_prepare__ functions where necessary */
- for (i = 0; i < nout; ++i) {
- if (prepare_ufunc_output(ufunc, &op[nin+i],
- arr_prep[i], arr_prep_args, i) < 0) {
+ /* Validate that the prepare_ufunc_output didn't mess with pointers */
+ if (PyArray_BYTES(op_tmp) != PyArray_BYTES(op[i])) {
+ PyErr_SetString(PyExc_ValueError,
+ "The __array_prepare__ functions modified the data "
+ "pointer addresses in an invalid fashion");
+ Py_DECREF(op_tmp);
NpyIter_Deallocate(iter);
return -1;
}
+
+ /*
+ * Put the updated operand back and undo the DECREF above. If
+ * COPY_IF_OVERLAP made a temporary copy, the output will be copied in
+ * by UPDATEIFCOPY even if op[i] was changed.
+ */
+ op[i] = op_tmp;
+ Py_DECREF(op_tmp);
}
/* Only do the loop if the iteration size is non-zero */
@@ -1794,17 +1851,6 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
PyArray_Descr **iter_dtypes;
NPY_BEGIN_THREADS_DEF;
- /* Validate that the prepare_ufunc_output didn't mess with pointers */
- for (i = nin; i < nop; ++i) {
- if (PyArray_BYTES(op[i]) != PyArray_BYTES(op_it[i])) {
- PyErr_SetString(PyExc_ValueError,
- "The __array_prepare__ functions modified the data "
- "pointer addresses in an invalid fashion");
- NpyIter_Deallocate(iter);
- return -1;
- }
- }
-
/*
* Get the inner loop, with the possibility of specialization
* based on the fixed strides.
@@ -2265,7 +2311,8 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
for (i = 0; i < nin; ++i) {
op_flags[i] = NPY_ITER_READONLY |
NPY_ITER_COPY |
- NPY_ITER_ALIGNED;
+ NPY_ITER_ALIGNED |
+ NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE;
/*
* If READWRITE flag has been set for this operand,
* then clear default READONLY flag
@@ -2280,14 +2327,16 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
NPY_ITER_UPDATEIFCOPY|
NPY_ITER_ALIGNED|
NPY_ITER_ALLOCATE|
- NPY_ITER_NO_BROADCAST;
+ NPY_ITER_NO_BROADCAST|
+ NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE;
}
iter_flags = ufunc->iter_flags |
NPY_ITER_MULTI_INDEX |
NPY_ITER_REFS_OK |
NPY_ITER_REDUCE_OK |
- NPY_ITER_ZEROSIZE_OK;
+ NPY_ITER_ZEROSIZE_OK |
+ NPY_ITER_COPY_IF_OVERLAP;
/* Create the iterator */
iter = NpyIter_AdvancedNew(nop, op, iter_flags,
@@ -3174,11 +3223,16 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
!PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(out)))) {
need_outer_iterator = 1;
}
+ /* If input and output overlap in memory, use iterator to figure it out */
+ else if (out != NULL && solve_may_share_memory(out, arr, NPY_MAY_SHARE_BOUNDS) != 0) {
+ need_outer_iterator = 1;
+ }
if (need_outer_iterator) {
int ndim_iter = 0;
npy_uint32 flags = NPY_ITER_ZEROSIZE_OK|
- NPY_ITER_REFS_OK;
+ NPY_ITER_REFS_OK|
+ NPY_ITER_COPY_IF_OVERLAP;
PyArray_Descr **op_dtypes_param = NULL;
/*
@@ -3592,7 +3646,8 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind,
if (need_outer_iterator) {
npy_uint32 flags = NPY_ITER_ZEROSIZE_OK|
NPY_ITER_REFS_OK|
- NPY_ITER_MULTI_INDEX;
+ NPY_ITER_MULTI_INDEX|
+ NPY_ITER_COPY_IF_OVERLAP;
/*
* The way reduceat is set up, we can't do buffering,
@@ -3635,6 +3690,7 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind,
/* In case COPY or UPDATEIFCOPY occurred */
op[0] = NpyIter_GetOperandArray(iter)[0];
op[1] = NpyIter_GetOperandArray(iter)[1];
+ op[2] = NpyIter_GetOperandArray(iter)[2];
if (out == NULL) {
out = op[0];
@@ -4395,6 +4451,7 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
continue;
}
res = PyObject_CallFunction(wrap, "O(OOi)", mps[j], ufunc, args, i);
+ /* Handle __array_wrap__ that does not accept a context argument */
if (res == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Clear();
res = PyObject_CallFunctionObjArgs(wrap, mps[j], NULL);
@@ -4403,9 +4460,6 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
if (res == NULL) {
goto fail;
}
- else if (res == Py_None) {
- Py_DECREF(res);
- }
else {
Py_DECREF(mps[j]);
retobj[i] = res;
@@ -5259,11 +5313,6 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
op1_array = (PyArrayObject *)op1;
- iter = (PyArrayMapIterObject *)PyArray_MapIterArray(op1_array, idx);
- if (iter == NULL) {
- goto fail;
- }
-
/* Create second operand from number array if needed. */
if (op2 != NULL) {
op2_array = (PyArrayObject *)PyArray_FromAny(op2, NULL,
@@ -5271,7 +5320,17 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
if (op2_array == NULL) {
goto fail;
}
+ }
+ /* Create map iterator */
+ iter = (PyArrayMapIterObject *)PyArray_MapIterArrayCopyIfOverlap(
+ op1_array, idx, 1, op2_array);
+ if (iter == NULL) {
+ goto fail;
+ }
+ op1_array = iter->array; /* May be updateifcopied on overlap */
+
+ if (op2 != NULL) {
/*
* May need to swap axes so that second operand is
* iterated over correctly
diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py
index 6c804a3b7..9aa7b2609 100644
--- a/numpy/core/tests/test_arrayprint.py
+++ b/numpy/core/tests/test_arrayprint.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import division, absolute_import, print_function
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index e443b3be0..94391f84c 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -1118,11 +1118,15 @@ class TestDateTime(TestCase):
assert_warns(FutureWarning, op, td_other, td_nat)
assert_warns(FutureWarning, np.not_equal, dt_nat, dt_nat)
+ assert_warns(FutureWarning, np.not_equal, td_nat, td_nat)
+
+ with suppress_warnings() as sup:
+ sup.record(FutureWarning)
assert_(np.not_equal(dt_nat, dt_other))
assert_(np.not_equal(dt_other, dt_nat))
- assert_warns(FutureWarning, np.not_equal, td_nat, td_nat)
assert_(np.not_equal(td_nat, td_other))
assert_(np.not_equal(td_other, td_nat))
+ self.assertEqual(len(sup.log), 0)
def test_datetime_minmax(self):
# The metadata of the result should become the GCD
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index c52d480a7..c0143aae3 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -620,5 +620,12 @@ def test_rational_dtype():
assert_equal(np.array([x,x]).dtype, np.dtype(rational))
+def test_dtypes_are_true():
+ # test for gh-6294
+ assert bool(np.dtype('f8'))
+ assert bool(np.dtype('i8'))
+ assert bool(np.dtype([('a', 'i8'), ('b', 'f4')]))
+
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_getlimits.py b/numpy/core/tests/test_getlimits.py
index 600f8f52c..4adb80f7f 100644
--- a/numpy/core/tests/test_getlimits.py
+++ b/numpy/core/tests/test_getlimits.py
@@ -7,8 +7,10 @@ import numpy as np
from numpy.core import finfo, iinfo
from numpy import half, single, double, longdouble
from numpy.testing import (
- TestCase, run_module_suite, assert_equal
+ TestCase, run_module_suite, assert_equal, assert_
)
+from numpy.core.getlimits import (_discovered_machar, _float16_ma, _float32_ma,
+ _float64_ma, _float128_ma, _float80_ma)
##################################################
@@ -87,5 +89,42 @@ def test_instances():
iinfo(10)
finfo(3.0)
+
+def assert_ma_equal(discovered, ma_like):
+ # Check MachAr-like objects same as calculated MachAr instances
+ for key, value in discovered.__dict__.items():
+ assert_equal(value, getattr(ma_like, key))
+ if hasattr(value, 'shape'):
+ assert_equal(value.shape, getattr(ma_like, key).shape)
+ assert_equal(value.dtype, getattr(ma_like, key).dtype)
+
+
+def test_known_types():
+ # Test we are correctly compiling parameters for known types
+ for ftype, ma_like in ((np.float16, _float16_ma),
+ (np.float32, _float32_ma),
+ (np.float64, _float64_ma)):
+ assert_ma_equal(_discovered_machar(ftype), ma_like)
+ # Suppress warning for broken discovery of double double on PPC
+ with np.errstate(all='ignore'):
+ ld_ma = _discovered_machar(np.longdouble)
+ bytes = np.dtype(np.longdouble).itemsize
+ if (ld_ma.it, ld_ma.maxexp) == (63, 16384) and bytes in (12, 16):
+ # 80-bit extended precision
+ assert_ma_equal(ld_ma, _float80_ma)
+ elif (ld_ma.it, ld_ma.maxexp) == (112, 16384) and bytes == 16:
+ # IEE 754 128-bit
+ assert_ma_equal(ld_ma, _float128_ma)
+
+
+def test_plausible_finfo():
+ # Assert that finfo returns reasonable results for all types
+ for ftype in np.sctypes['float'] + np.sctypes['complex']:
+ info = np.finfo(ftype)
+ assert_(info.nmant > 1)
+ assert_(info.minexp < -1)
+ assert_(info.maxexp > 1)
+
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_mem_overlap.py b/numpy/core/tests/test_mem_overlap.py
index acca53856..a95a03fa4 100644
--- a/numpy/core/tests/test_mem_overlap.py
+++ b/numpy/core/tests/test_mem_overlap.py
@@ -4,9 +4,11 @@ import sys
import itertools
import numpy as np
-from numpy.testing import run_module_suite, assert_, assert_raises, assert_equal
+from numpy.testing import (run_module_suite, assert_, assert_raises, assert_equal,
+ assert_array_equal, assert_allclose)
from numpy.core.multiarray_tests import solve_diophantine, internal_overlap
+from numpy.core import umath_tests
from numpy.lib.stride_tricks import as_strided
from numpy.compat import long
@@ -84,7 +86,7 @@ def _check_assignment(srcidx, dstidx):
def test_overlapping_assignments():
- """Test automatically generated assignments which overlap in memory."""
+ # Test automatically generated assignments which overlap in memory.
inds = _indices(ndims)
@@ -107,7 +109,6 @@ def test_diophantine_fuzz():
min_count = 500//(ndim + 1)
- numbers = []
while min(feasible_count, infeasible_count) < min_count:
# Ensure big and small integer problems
A_max = 1 + rng.randint(0, 11, dtype=np.intp)**6
@@ -252,13 +253,12 @@ def test_may_share_memory_manual():
check_may_share_memory_exact(x, x.copy())
-def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count):
- # Check that overlap problems with common strides are solved with
- # little work.
- x = np.zeros([17,34,71,97], dtype=np.int16)
-
+def iter_random_view_pairs(x, same_steps=True, equal_size=False):
rng = np.random.RandomState(1234)
+ if equal_size and same_steps:
+ raise ValueError()
+
def random_slice(n, step):
start = rng.randint(0, n+1, dtype=np.intp)
stop = rng.randint(start, n+1, dtype=np.intp)
@@ -267,31 +267,93 @@ def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count):
step *= -1
return slice(start, stop, step)
- feasible = 0
- infeasible = 0
+ def random_slice_fixed_size(n, step, size):
+ start = rng.randint(0, n+1 - size*step)
+ stop = start + (size-1)*step + 1
+ if rng.randint(0, 2) == 0:
+ stop, start = start-1, stop-1
+ if stop < 0:
+ stop = None
+ step *= -1
+ return slice(start, stop, step)
- while min(feasible, infeasible) < min_count:
+ # First a few regular views
+ yield x, x
+ for j in range(1, 7, 3):
+ yield x[j:], x[:-j]
+ yield x[...,j:], x[...,:-j]
+
+ # An array with zero stride internal overlap
+ strides = list(x.strides)
+ strides[0] = 0
+ xp = as_strided(x, shape=x.shape, strides=strides)
+ yield x, xp
+ yield xp, xp
+
+ # An array with non-zero stride internal overlap
+ strides = list(x.strides)
+ if strides[0] > 1:
+ strides[0] = 1
+ xp = as_strided(x, shape=x.shape, strides=strides)
+ yield x, xp
+ yield xp, xp
+
+ # Then discontiguous views
+ while True:
steps = tuple(rng.randint(1, 11, dtype=np.intp)
if rng.randint(0, 5, dtype=np.intp) == 0 else 1
for j in range(x.ndim))
- if same_steps:
+ s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps))
+
+ t1 = np.arange(x.ndim)
+ rng.shuffle(t1)
+
+ if equal_size:
+ t2 = t1
+ else:
+ t2 = np.arange(x.ndim)
+ rng.shuffle(t2)
+
+ a = x[s1]
+
+ if equal_size:
+ if a.size == 0:
+ continue
+
+ steps2 = tuple(rng.randint(1, max(2, p//(1+pa)))
+ if rng.randint(0, 5) == 0 else 1
+ for p, s, pa in zip(x.shape, s1, a.shape))
+ s2 = tuple(random_slice_fixed_size(p, s, pa)
+ for p, s, pa in zip(x.shape, steps2, a.shape))
+ elif same_steps:
steps2 = steps
else:
steps2 = tuple(rng.randint(1, 11, dtype=np.intp)
if rng.randint(0, 5, dtype=np.intp) == 0 else 1
for j in range(x.ndim))
- t1 = np.arange(x.ndim)
- rng.shuffle(t1)
-
- t2 = np.arange(x.ndim)
- rng.shuffle(t2)
+ if not equal_size:
+ s2 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps2))
- s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps))
- s2 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps2))
- a = x[s1].transpose(t1)
+ a = a.transpose(t1)
b = x[s2].transpose(t2)
+ yield a, b
+
+
+def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count):
+ # Check that overlap problems with common strides are solved with
+ # little work.
+ x = np.zeros([17,34,71,97], dtype=np.int16)
+
+ feasible = 0
+ infeasible = 0
+
+ pair_iter = iter_random_view_pairs(x, same_steps)
+
+ while min(feasible, infeasible) < min_count:
+ a, b = next(pair_iter)
+
bounds_overlap = np.may_share_memory(a, b)
may_share_answer = np.may_share_memory(a, b)
easy_answer = np.may_share_memory(a, b, max_work=get_max_work(a, b))
@@ -299,11 +361,10 @@ def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count):
if easy_answer != exact_answer:
# assert_equal is slow...
- assert_equal(easy_answer, exact_answer, err_msg=repr((s1, s2)))
+ assert_equal(easy_answer, exact_answer)
if may_share_answer != bounds_overlap:
- assert_equal(may_share_answer, bounds_overlap,
- err_msg=repr((s1, s2)))
+ assert_equal(may_share_answer, bounds_overlap)
if bounds_overlap:
if exact_answer:
@@ -524,5 +585,364 @@ def test_non_ndarray_inputs():
assert_(np.may_share_memory(cls(x[1::3]), x[::2]))
+def view_element_first_byte(x):
+ """Construct an array viewing the first byte of each element of `x`"""
+ from numpy.lib.stride_tricks import DummyArray
+ interface = dict(x.__array_interface__)
+ interface['typestr'] = '|b1'
+ interface['descr'] = [('', '|b1')]
+ return np.asarray(DummyArray(interface, x))
+
+
+def assert_copy_equivalent(operation, args, out, **kwargs):
+ """
+ Check that operation(*args, out=out) produces results
+ equivalent to out[...] = operation(*args, out=out.copy())
+ """
+
+ kwargs['out'] = out
+ kwargs2 = dict(kwargs)
+ kwargs2['out'] = out.copy()
+
+ out_orig = out.copy()
+ out[...] = operation(*args, **kwargs2)
+ expected = out.copy()
+ out[...] = out_orig
+
+ got = operation(*args, **kwargs).copy()
+
+ if (got != expected).any():
+ assert_equal(got, expected)
+
+
+class TestUFunc(object):
+ """
+ Test ufunc call memory overlap handling
+ """
+
+ def check_unary_fuzz(self, operation, get_out_axis_size, dtype=np.int16,
+ count=5000):
+ shapes = [7, 13, 8, 21, 29, 32]
+
+ rng = np.random.RandomState(1234)
+
+ for ndim in range(1, 6):
+ x = rng.randint(0, 2**16, size=shapes[:ndim]).astype(dtype)
+
+ it = iter_random_view_pairs(x, same_steps=False, equal_size=True)
+
+ min_count = count // (ndim + 1)**2
+
+ overlapping = 0
+ while overlapping < min_count:
+ a, b = next(it)
+
+ a_orig = a.copy()
+ b_orig = b.copy()
+
+ if get_out_axis_size is None:
+ assert_copy_equivalent(operation, [a], out=b)
+
+ if np.shares_memory(a, b):
+ overlapping += 1
+ else:
+ for axis in itertools.chain(range(ndim), [None]):
+ a[...] = a_orig
+ b[...] = b_orig
+
+ # Determine size for reduction axis (None if scalar)
+ outsize, scalarize = get_out_axis_size(a, b, axis)
+ if outsize == 'skip':
+ continue
+
+ # Slice b to get an output array of the correct size
+ sl = [slice(None)] * ndim
+ if axis is None:
+ if outsize is None:
+ sl = [slice(0, 1)] + [0]*(ndim - 1)
+ else:
+ sl = [slice(0, outsize)] + [0]*(ndim - 1)
+ else:
+ if outsize is None:
+ k = b.shape[axis]//2
+ if ndim == 1:
+ sl[axis] = slice(k, k + 1)
+ else:
+ sl[axis] = k
+ else:
+ assert b.shape[axis] >= outsize
+ sl[axis] = slice(0, outsize)
+ b_out = b[tuple(sl)]
+
+ if scalarize:
+ b_out = b_out.reshape([])
+
+ if np.shares_memory(a, b_out):
+ overlapping += 1
+
+ # Check result
+ assert_copy_equivalent(operation, [a], out=b_out, axis=axis)
+
+ def test_unary_ufunc_call_fuzz(self):
+ self.check_unary_fuzz(np.invert, None, np.int16)
+
+ def test_binary_ufunc_accumulate_fuzz(self):
+ def get_out_axis_size(a, b, axis):
+ if axis is None:
+ if a.ndim == 1:
+ return a.size, False
+ else:
+ return 'skip', False # accumulate doesn't support this
+ else:
+ return a.shape[axis], False
+
+ self.check_unary_fuzz(np.add.accumulate, get_out_axis_size,
+ dtype=np.int16, count=500)
+
+ def test_binary_ufunc_reduce_fuzz(self):
+ def get_out_axis_size(a, b, axis):
+ return None, (axis is None or a.ndim == 1)
+
+ self.check_unary_fuzz(np.add.reduce, get_out_axis_size,
+ dtype=np.int16, count=500)
+
+ def test_binary_ufunc_reduceat_fuzz(self):
+ def get_out_axis_size(a, b, axis):
+ if axis is None:
+ if a.ndim == 1:
+ return a.size, False
+ else:
+ return 'skip', False # reduceat doesn't support this
+ else:
+ return a.shape[axis], False
+
+ def do_reduceat(a, out, axis):
+ if axis is None:
+ size = len(a)
+ step = size//len(out)
+ else:
+ size = a.shape[axis]
+ step = a.shape[axis] // out.shape[axis]
+ idx = np.arange(0, size, step)
+ return np.add.reduceat(a, idx, out=out, axis=axis)
+
+ self.check_unary_fuzz(do_reduceat, get_out_axis_size,
+ dtype=np.int16, count=500)
+
+ def test_binary_ufunc_reduceat_manual(self):
+ def check(ufunc, a, ind, out):
+ c1 = ufunc.reduceat(a.copy(), ind.copy(), out=out.copy())
+ c2 = ufunc.reduceat(a, ind, out=out)
+ assert_array_equal(c1, c2)
+
+ # Exactly same input/output arrays
+ a = np.arange(10000, dtype=np.int16)
+ check(np.add, a, a[::-1].copy(), a)
+
+ # Overlap with index
+ a = np.arange(10000, dtype=np.int16)
+ check(np.add, a, a[::-1], a)
+
+ def test_unary_gufunc_fuzz(self):
+ shapes = [7, 13, 8, 21, 29, 32]
+ gufunc = umath_tests.euclidean_pdist
+
+ rng = np.random.RandomState(1234)
+
+ for ndim in range(2, 6):
+ x = rng.rand(*shapes[:ndim])
+
+ it = iter_random_view_pairs(x, same_steps=False, equal_size=True)
+
+ min_count = 500 // (ndim + 1)**2
+
+ overlapping = 0
+ while overlapping < min_count:
+ a, b = next(it)
+
+ if min(a.shape[-2:]) < 2 or min(b.shape[-2:]) < 2 or a.shape[-1] < 2:
+ continue
+
+ # Ensure the shapes are so that euclidean_pdist is happy
+ if b.shape[-1] > b.shape[-2]:
+ b = b[...,0,:]
+ else:
+ b = b[...,:,0]
+
+ n = a.shape[-2]
+ p = n * (n - 1) // 2
+ if p <= b.shape[-1] and p > 0:
+ b = b[...,:p]
+ else:
+ n = max(2, int(np.sqrt(b.shape[-1]))//2)
+ p = n * (n - 1) // 2
+ a = a[...,:n,:]
+ b = b[...,:p]
+
+ # Call
+ if np.shares_memory(a, b):
+ overlapping += 1
+
+ with np.errstate(over='ignore', invalid='ignore'):
+ assert_copy_equivalent(gufunc, [a], out=b)
+
+ def test_ufunc_at_manual(self):
+ def check(ufunc, a, ind, b=None):
+ a0 = a.copy()
+ if b is None:
+ ufunc.at(a0, ind.copy())
+ c1 = a0.copy()
+ ufunc.at(a, ind)
+ c2 = a.copy()
+ else:
+ ufunc.at(a0, ind.copy(), b.copy())
+ c1 = a0.copy()
+ ufunc.at(a, ind, b)
+ c2 = a.copy()
+ assert_array_equal(c1, c2)
+
+ # Overlap with index
+ a = np.arange(10000, dtype=np.int16)
+ check(np.invert, a[::-1], a)
+
+ # Overlap with second data array
+ a = np.arange(100, dtype=np.int16)
+ ind = np.arange(0, 100, 2, dtype=np.int16)
+ check(np.add, a, ind, a[25:75])
+
+ def test_unary_ufunc_1d_manual(self):
+ # Exercise branches in PyArray_EQUIVALENTLY_ITERABLE
+
+ def check(a, b):
+ a_orig = a.copy()
+ b_orig = b.copy()
+
+ b0 = b.copy()
+ c1 = ufunc(a, out=b0)
+ c2 = ufunc(a, out=b)
+ assert_array_equal(c1, c2)
+
+ # Trigger "fancy ufunc loop" code path
+ mask = view_element_first_byte(b).view(np.bool_)
+
+ a[...] = a_orig
+ b[...] = b_orig
+ c1 = ufunc(a, out=b.copy(), where=mask.copy()).copy()
+
+ a[...] = a_orig
+ b[...] = b_orig
+ c2 = ufunc(a, out=b, where=mask.copy()).copy()
+
+ # Also, mask overlapping with output
+ a[...] = a_orig
+ b[...] = b_orig
+ c3 = ufunc(a, out=b, where=mask).copy()
+
+ assert_array_equal(c1, c2)
+ assert_array_equal(c1, c3)
+
+ dtypes = [np.int8, np.int16, np.int32, np.int64, np.float32,
+ np.float64, np.complex64, np.complex128]
+ dtypes = [np.dtype(x) for x in dtypes]
+
+ for dtype in dtypes:
+ if np.issubdtype(dtype, np.integer):
+ ufunc = np.invert
+ else:
+ ufunc = np.reciprocal
+
+ n = 1000
+ k = 10
+ indices = [
+ np.index_exp[:n],
+ np.index_exp[k:k+n],
+ np.index_exp[n-1::-1],
+ np.index_exp[k+n-1:k-1:-1],
+ np.index_exp[:2*n:2],
+ np.index_exp[k:k+2*n:2],
+ np.index_exp[2*n-1::-2],
+ np.index_exp[k+2*n-1:k-1:-2],
+ ]
+
+ for xi, yi in itertools.product(indices, indices):
+ v = np.arange(1, 1 + n*2 + k, dtype=dtype)
+ x = v[xi]
+ y = v[yi]
+
+ with np.errstate(all='ignore'):
+ check(x, y)
+
+ # Scalar cases
+ check(x[:1], y)
+ check(x[-1:], y)
+ check(x[:1].reshape([]), y)
+ check(x[-1:].reshape([]), y)
+
+ def test_unary_ufunc_where_same(self):
+ # Check behavior at wheremask overlap
+ ufunc = np.invert
+
+ def check(a, out, mask):
+ c1 = ufunc(a, out=out.copy(), where=mask.copy())
+ c2 = ufunc(a, out=out, where=mask)
+ assert_array_equal(c1, c2)
+
+ # Check behavior with same input and output arrays
+ x = np.arange(100).astype(np.bool_)
+ check(x, x, x)
+ check(x, x.copy(), x)
+ check(x, x, x.copy())
+
+ def test_binary_ufunc_1d_manual(self):
+ ufunc = np.add
+
+ def check(a, b, c):
+ c0 = c.copy()
+ c1 = ufunc(a, b, out=c0)
+ c2 = ufunc(a, b, out=c)
+ assert_array_equal(c1, c2)
+
+ for dtype in [np.int8, np.int16, np.int32, np.int64,
+ np.float32, np.float64, np.complex64, np.complex128]:
+ # Check different data dependency orders
+
+ n = 1000
+ k = 10
+
+ indices = []
+ for p in [1, 2]:
+ indices.extend([
+ np.index_exp[:p*n:p],
+ np.index_exp[k:k+p*n:p],
+ np.index_exp[p*n-1::-p],
+ np.index_exp[k+p*n-1:k-1:-p],
+ ])
+
+ for x, y, z in itertools.product(indices, indices, indices):
+ v = np.arange(6*n).astype(dtype)
+ x = v[x]
+ y = v[y]
+ z = v[z]
+
+ check(x, y, z)
+
+ # Scalar cases
+ check(x[:1], y, z)
+ check(x[-1:], y, z)
+ check(x[:1].reshape([]), y, z)
+ check(x[-1:].reshape([]), y, z)
+ check(x, y[:1], z)
+ check(x, y[-1:], z)
+ check(x, y[:1].reshape([]), z)
+ check(x, y[-1:].reshape([]), z)
+
+ def test_inplace_op_simple_manual(self):
+ rng = np.random.RandomState(1234)
+ x = rng.rand(200, 200) # bigger than bufsize
+
+ x += x.T
+ assert_array_equal(x - x.T, 0)
+
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_memmap.py b/numpy/core/tests/test_memmap.py
index 2f95910ec..f643dacc1 100644
--- a/numpy/core/tests/test_memmap.py
+++ b/numpy/core/tests/test_memmap.py
@@ -4,6 +4,7 @@ import sys
import os
import shutil
from tempfile import NamedTemporaryFile, TemporaryFile, mktemp, mkdtemp
+import mmap
from numpy import (
memmap, sum, average, product, ndarray, isscalar, add, subtract, multiply)
@@ -188,6 +189,11 @@ class TestMemmap(TestCase):
assert_(fp[1:, :-1].__class__ is MemmapSubClass)
assert(fp[[0, 1]].__class__ is MemmapSubClass)
+ def test_mmap_offset_greater_than_allocation_granularity(self):
+ size = 5 * mmap.ALLOCATIONGRANULARITY
+ offset = mmap.ALLOCATIONGRANULARITY + 1
+ fp = memmap(self.tmpfp, shape=size, mode='w+', offset=offset)
+ assert_(fp.offset == offset)
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 8bbfbc09c..8229f1e1a 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -8,6 +8,7 @@ import warnings
import operator
import io
import itertools
+import functools
import ctypes
import os
import gc
@@ -46,6 +47,32 @@ else:
EMPTY = None
+def _aligned_zeros(shape, dtype=float, order="C", align=None):
+ """Allocate a new ndarray with aligned memory."""
+ dtype = np.dtype(dtype)
+ if dtype == np.dtype(object):
+ # Can't do this, fall back to standard allocation (which
+ # should always be sufficiently aligned)
+ if align is not None:
+ raise ValueError("object array alignment not supported")
+ return np.zeros(shape, dtype=dtype, order=order)
+ if align is None:
+ align = dtype.alignment
+ if not hasattr(shape, '__len__'):
+ shape = (shape,)
+ size = functools.reduce(operator.mul, shape) * dtype.itemsize
+ buf = np.empty(size + align + 1, np.uint8)
+ offset = buf.__array_interface__['data'][0] % align
+ if offset != 0:
+ offset = align - offset
+ # Note: slices producing 0-size arrays do not necessarily change
+ # data pointer --- so we use and allocate size+1
+ buf = buf[offset:offset+size+1][:-1]
+ data = np.ndarray(shape, dtype, buf, order=order)
+ data.fill(0)
+ return data
+
+
class TestFlags(TestCase):
def setUp(self):
self.a = np.arange(10)
@@ -2326,6 +2353,28 @@ class TestMethods(TestCase):
assert_raises(TypeError, np.dot, c, A)
assert_raises(TypeError, np.dot, A, c)
+ def test_dot_out_mem_overlap(self):
+ np.random.seed(1)
+
+ # Test BLAS and non-BLAS code paths, including all dtypes
+ # that dot() supports
+ dtypes = [np.dtype(code) for code in np.typecodes['All']
+ if code not in 'USVM']
+ for dtype in dtypes:
+ a = np.random.rand(3, 3).astype(dtype)
+
+ # Valid dot() output arrays must be aligned
+ b = _aligned_zeros((3, 3), dtype=dtype)
+ b[...] = np.random.rand(3, 3)
+
+ y = np.dot(a, b)
+ x = np.dot(a, b, out=b)
+ assert_equal(x, y, err_msg=repr(dtype))
+
+ # Check invalid output array
+ assert_raises(ValueError, np.dot, a, b, out=b[::2])
+ assert_raises(ValueError, np.dot, a, b, out=b.T)
+
def test_diagonal(self):
a = np.arange(12).reshape((3, 4))
assert_equal(a.diagonal(), [0, 5, 10])
@@ -4407,6 +4456,12 @@ class TestStats(TestCase):
self.omat = np.array([Decimal(repr(r)) for r in self.rmat.flat])
self.omat = self.omat.reshape(4, 5)
+ def test_python_type(self):
+ for x in (np.float16(1.), 1, 1., 1+0j):
+ assert_equal(np.mean([x]), 1.)
+ assert_equal(np.std([x]), 0.)
+ assert_equal(np.var([x]), 0.)
+
def test_keepdims(self):
mat = np.eye(3)
for f in self.funcs:
diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py
index f5096e023..1863f36f7 100644
--- a/numpy/core/tests/test_nditer.py
+++ b/numpy/core/tests/test_nditer.py
@@ -1139,6 +1139,94 @@ def test_iter_common_dtype():
assert_equal(i.dtypes[1], np.dtype('c16'))
assert_equal(i.dtypes[2], np.dtype('c16'))
+def test_iter_copy_if_overlap():
+ # Ensure the iterator makes copies on read/write overlap, if requested
+
+ # Copy not needed, 1 op
+ for flag in ['readonly', 'writeonly', 'readwrite']:
+ a = arange(10)
+ i = nditer([a], ['copy_if_overlap'], [[flag]])
+ assert_(i.operands[0] is a)
+
+ # Copy needed, 2 ops, read-write overlap
+ x = arange(10)
+ a = x[1:]
+ b = x[:-1]
+ i = nditer([a, b], ['copy_if_overlap'], [['readonly'], ['readwrite']])
+ assert_(not np.shares_memory(*i.operands))
+
+ # Copy not needed with elementwise, 2 ops, exactly same arrays
+ x = arange(10)
+ a = x
+ b = x
+ i = nditer([a, b], ['copy_if_overlap'], [['readonly', 'overlap_assume_elementwise'],
+ ['readwrite', 'overlap_assume_elementwise']])
+ assert_(i.operands[0] is a and i.operands[1] is b)
+ i = nditer([a, b], ['copy_if_overlap'], [['readonly'], ['readwrite']])
+ assert_(i.operands[0] is a and not np.shares_memory(i.operands[1], b))
+
+ # Copy not needed, 2 ops, no overlap
+ x = arange(10)
+ a = x[::2]
+ b = x[1::2]
+ i = nditer([a, b], ['copy_if_overlap'], [['readonly'], ['writeonly']])
+ assert_(i.operands[0] is a and i.operands[1] is b)
+
+ # Copy needed, 2 ops, read-write overlap
+ x = arange(4, dtype=np.int8)
+ a = x[3:]
+ b = x.view(np.int32)[:1]
+ i = nditer([a, b], ['copy_if_overlap'], [['readonly'], ['writeonly']])
+ assert_(not np.shares_memory(*i.operands))
+
+ # Copy needed, 3 ops, read-write overlap
+ for flag in ['writeonly', 'readwrite']:
+ x = np.ones([10, 10])
+ a = x
+ b = x.T
+ c = x
+ i = nditer([a, b, c], ['copy_if_overlap'],
+ [['readonly'], ['readonly'], [flag]])
+ a2, b2, c2 = i.operands
+ assert_(not np.shares_memory(a2, c2))
+ assert_(not np.shares_memory(b2, c2))
+
+ # Copy not needed, 3 ops, read-only overlap
+ x = np.ones([10, 10])
+ a = x
+ b = x.T
+ c = x
+ i = nditer([a, b, c], ['copy_if_overlap'],
+ [['readonly'], ['readonly'], ['readonly']])
+ a2, b2, c2 = i.operands
+ assert_(a is a2)
+ assert_(b is b2)
+ assert_(c is c2)
+
+ # Copy not needed, 3 ops, read-only overlap
+ x = np.ones([10, 10])
+ a = x
+ b = np.ones([10, 10])
+ c = x.T
+ i = nditer([a, b, c], ['copy_if_overlap'],
+ [['readonly'], ['writeonly'], ['readonly']])
+ a2, b2, c2 = i.operands
+ assert_(a is a2)
+ assert_(b is b2)
+ assert_(c is c2)
+
+ # Copy not needed, 3 ops, write-only overlap
+ x = np.arange(7)
+ a = x[:3]
+ b = x[3:6]
+ c = x[4:7]
+ i = nditer([a, b, c], ['copy_if_overlap'],
+ [['readonly'], ['writeonly'], ['writeonly']])
+ a2, b2, c2 = i.operands
+ assert_(a is a2)
+ assert_(b is b2)
+ assert_(c is c2)
+
def test_iter_op_axes():
# Check that custom axes work
@@ -2320,7 +2408,11 @@ def test_iter_reduction():
assert_equal(i[1].strides, (0,))
# Do the reduction
for x, y in i:
- y[...] += x
+ # Use a for loop instead of ``y[...] += x``
+ # (equivalent to ``y[...] = y[...].copy() + x``),
+ # because y has zero strides we use for the reduction
+ for j in range(len(y)):
+ y[j] += x[j]
# Since no axes were specified, should have allocated a scalar
assert_equal(i.operands[1].ndim, 0)
assert_equal(i.operands[1], np.sum(a))
@@ -2371,7 +2463,11 @@ def test_iter_buffering_reduction():
assert_equal(i[1].strides, (0,))
# Do the reduction
for x, y in i:
- y[...] += x
+ # Use a for loop instead of ``y[...] += x``
+ # (equivalent to ``y[...] = y[...].copy() + x``),
+ # because y has zero strides we use for the reduction
+ for j in range(len(y)):
+ y[j] += x[j]
assert_equal(b, np.sum(a, axis=1))
# Iterator inner double loop was wrong on this one
diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py
index bd1fc014e..74a3be533 100644
--- a/numpy/core/tests/test_records.py
+++ b/numpy/core/tests/test_records.py
@@ -28,6 +28,32 @@ class TestFromrecords(TestCase):
assert_equal(r['col2'].dtype.itemsize, 3)
assert_equal(r['col3'].dtype.kind, 'f')
+ def test_fromrecords_0len(self):
+ """ Verify fromrecords works with a 0-length input """
+ dtype = [('a', np.float), ('b', np.float)]
+ r = np.rec.fromrecords([], dtype=dtype)
+ assert_equal(r.shape, (0,))
+
+ def test_fromrecords_2d(self):
+ data = [
+ [(1, 2), (3, 4), (5, 6)],
+ [(6, 5), (4, 3), (2, 1)]
+ ]
+ expected_a = [[1, 3, 5], [6, 4, 2]]
+ expected_b = [[2, 4, 6], [5, 3, 1]]
+
+ # try with dtype
+ r1 = np.rec.fromrecords(data, dtype=[('a', int), ('b', int)])
+ assert_equal(r1['a'], expected_a)
+ assert_equal(r1['b'], expected_b)
+
+ # try with names
+ r2 = np.rec.fromrecords(data, names=['a', 'b'])
+ assert_equal(r2['a'], expected_a)
+ assert_equal(r2['b'], expected_b)
+
+ assert_equal(r1, r2)
+
def test_method_array(self):
r = np.rec.array(asbytes('abcdefg') * 100, formats='i2,a3,i4', shape=3, byteorder='big')
assert_equal(r[1].item(), (25444, asbytes('efg'), 1633837924))
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index fa15554b2..d83b7dccd 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -1422,6 +1422,19 @@ class TestSpecialMethods(TestCase):
a = A()
self.assertRaises(RuntimeError, ncu.maximum, a, a)
+ def test_none_wrap(self):
+ # Tests that issue #8507 is resolved. Previously, this would segfault
+
+ class A(object):
+ def __array__(self):
+ return np.zeros(1)
+
+ def __array_wrap__(self, arr, context=None):
+ return None
+
+ a = A()
+ assert_equal(ncu.maximum(a, a), None)
+
def test_default_prepare(self):
class with_wrap(object):
@@ -1452,6 +1465,22 @@ class TestSpecialMethods(TestCase):
assert_equal(x, np.array(2))
assert_equal(type(x), with_prepare)
+ def test_prepare_out(self):
+
+ class with_prepare(np.ndarray):
+ __array_priority__ = 10
+
+ def __array_prepare__(self, arr, context):
+ return np.array(arr).view(type=with_prepare)
+
+ a = np.array([1]).view(type=with_prepare)
+ x = np.add(a, a, a)
+ # Returned array is new, because of the strange
+ # __array_prepare__ above
+ assert_(not np.shares_memory(x, a))
+ assert_equal(x, np.array([2]))
+ assert_equal(type(x), with_prepare)
+
def test_failing_prepare(self):
class A(object):
@@ -2092,8 +2121,8 @@ def test_nextafter():
def test_nextafterf():
return _test_nextafter(np.float32)
-@dec.knownfailureif(sys.platform == 'win32' or on_powerpc(),
- "Long double support buggy on win32 and PPC, ticket 1664.")
+@dec.knownfailureif(sys.platform == 'win32',
+ "Long double support buggy on win32, ticket 1664.")
def test_nextafterl():
return _test_nextafter(np.longdouble)
@@ -2115,8 +2144,8 @@ def test_spacing():
def test_spacingf():
return _test_spacing(np.float32)
-@dec.knownfailureif(sys.platform == 'win32' or on_powerpc(),
- "Long double support buggy on win32 and PPC, ticket 1664.")
+@dec.knownfailureif(sys.platform == 'win32',
+ "Long double support buggy on win32, ticket 1664.")
def test_spacingl():
return _test_spacing(np.longdouble)
diff --git a/numpy/core/tests/test_unicode.py b/numpy/core/tests/test_unicode.py
index 9935b60ad..f2c501235 100644
--- a/numpy/core/tests/test_unicode.py
+++ b/numpy/core/tests/test_unicode.py
@@ -15,7 +15,17 @@ if sys.version_info[:2] >= (3, 3):
def buffer_length(arr):
if isinstance(arr, unicode):
arr = str(arr)
- return (sys.getsizeof(arr+"a") - sys.getsizeof(arr)) * len(arr)
+ if not arr:
+ charmax = 0
+ else:
+ charmax = max([ord(c) for c in arr])
+ if charmax < 256:
+ size = 1
+ elif charmax < 65536:
+ size = 2
+ else:
+ size = 4
+ return size * len(arr)
v = memoryview(arr)
if v.shape is None:
return len(v) * v.itemsize
diff --git a/numpy/distutils/conv_template.py b/numpy/distutils/conv_template.py
index ff9431798..f2ed51334 100644
--- a/numpy/distutils/conv_template.py
+++ b/numpy/distutils/conv_template.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
"""
takes templated file .xxx.src and produces .xxx file where .xxx is
.i or .c or .h, using the following template rules
diff --git a/numpy/distutils/from_template.py b/numpy/distutils/from_template.py
index ff2130297..b19c7cc0b 100644
--- a/numpy/distutils/from_template.py
+++ b/numpy/distutils/from_template.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
"""
process_file(filename)
diff --git a/numpy/distutils/mingw32ccompiler.py b/numpy/distutils/mingw32ccompiler.py
index 0a0d651ad..65fd2cc82 100644
--- a/numpy/distutils/mingw32ccompiler.py
+++ b/numpy/distutils/mingw32ccompiler.py
@@ -248,25 +248,37 @@ class Mingw32CCompiler(distutils.cygwinccompiler.CygwinCCompiler):
def find_python_dll():
- maj, min, micro = [int(i) for i in sys.version_info[:3]]
- dllname = 'python%d%d.dll' % (maj, min)
- print("Looking for %s" % dllname)
-
# We can't do much here:
# - find it in the virtualenv (sys.prefix)
# - find it in python main dir (sys.base_prefix, if in a virtualenv)
# - in system32,
# - ortherwise (Sxs), I don't know how to get it.
- lib_dirs = [sys.prefix, sys.base_prefix, os.path.join(sys.prefix, 'lib')]
- try:
- lib_dirs.append(os.path.join(os.environ['SYSTEMROOT'], 'system32'))
- except KeyError:
- pass
-
- for d in lib_dirs:
- dll = os.path.join(d, dllname)
- if os.path.exists(dll):
- return dll
+ stems = [sys.prefix]
+ if sys.base_prefix != sys.prefix:
+ stems.append(sys.base_prefix)
+
+ sub_dirs = ['', 'lib', 'bin']
+ # generate possible combinations of directory trees and sub-directories
+ lib_dirs = []
+ for stem in stems:
+ for folder in sub_dirs:
+ lib_dirs = os.path.join(stem, folder)
+
+ # add system directory as well
+ if 'SYSTEMROOT' in os.environ:
+ lib_dirs.append(os.path.join(os.environ['SYSTEMROOT'], 'System32'))
+
+ # search in the file system for possible candidates
+ major_version, minor_version = tuple(sys.version_info[:2])
+ patterns = ['python%d%d.dll']
+
+ for pat in patterns:
+ dllname = pat % (major_version, minor_version)
+ print("Looking for %s" % dllname)
+ for folder in lib_dirs:
+ dll = os.path.join(folder, dllname)
+ if os.path.exists(dll):
+ return dll
raise ValueError("%s not found in %s" % (dllname, lib_dirs))
@@ -394,40 +406,70 @@ def build_import_library():
else:
raise ValueError("Unhandled arch %s" % arch)
-def _build_import_library_amd64():
- dll_file = find_python_dll()
+def _check_for_import_lib():
+ """Check if an import library for the Python runtime already exists."""
+ major_version, minor_version = tuple(sys.version_info[:2])
- out_name = "libpython%d%d.a" % tuple(sys.version_info[:2])
- out_file = os.path.join(sys.prefix, 'libs', out_name)
- if os.path.isfile(out_file):
- log.debug('Skip building import library: "%s" exists' %
- (out_file))
- return
+ # patterns for the file name of the library itself
+ patterns = ['libpython%d%d.a',
+ 'libpython%d%d.dll.a',
+ 'libpython%d.%d.dll.a']
- # didn't exist in virtualenv, maybe in base distribution?
- base_file = os.path.join(sys.base_prefix, 'libs', out_name)
- if os.path.isfile(base_file):
- log.debug('Skip building import library: "%s" exists', base_file)
- return
+ # directory trees that may contain the library
+ stems = [sys.prefix]
+ if sys.base_prefix != sys.prefix:
+ stems.append(sys.base_prefix)
- def_name = "python%d%d.def" % tuple(sys.version_info[:2])
- def_file = os.path.join(sys.prefix, 'libs', def_name)
+ # possible subdirectories within those trees where it is placed
+ sub_dirs = ['libs', 'lib']
+ # generate a list of candidate locations
+ candidates = []
+ for pat in patterns:
+ filename = pat % (major_version, minor_version)
+ for stem_dir in stems:
+ for folder in sub_dirs:
+ candidates.append(os.path.join(stem_dir, folder, filename))
+
+ # test the filesystem to see if we can find any of these
+ for fullname in candidates:
+ if os.path.isfile(fullname):
+ # already exists, in location given
+ return (True, fullname)
+
+ # needs to be built, preferred location given first
+ return (False, candidates[0])
+
+def _build_import_library_amd64():
+ out_exists, out_file = _check_for_import_lib()
+ if out_exists:
+ log.debug('Skip building import library: "%s" exists', out_file)
+ return
+
+ # get the runtime dll for which we are building import library
+ dll_file = find_python_dll()
log.info('Building import library (arch=AMD64): "%s" (from %s)' %
(out_file, dll_file))
+ # generate symbol list from this library
+ def_name = "python%d%d.def" % tuple(sys.version_info[:2])
+ def_file = os.path.join(sys.prefix, 'libs', def_name)
generate_def(dll_file, def_file)
+ # generate import library from this symbol list
cmd = ['dlltool', '-d', def_file, '-l', out_file]
subprocess.Popen(cmd)
def _build_import_library_x86():
""" Build the import libraries for Mingw32-gcc on Windows
"""
+ out_exists, out_file = _check_for_import_lib()
+ if out_exists:
+ log.debug('Skip building import library: "%s" exists', out_file)
+ return
+
lib_name = "python%d%d.lib" % tuple(sys.version_info[:2])
lib_file = os.path.join(sys.prefix, 'libs', lib_name)
- out_name = "libpython%d%d.a" % tuple(sys.version_info[:2])
- out_file = os.path.join(sys.prefix, 'libs', out_name)
if not os.path.isfile(lib_file):
# didn't find library file in virtualenv, try base distribution, too,
# and use that instead if found there
@@ -437,14 +479,6 @@ def _build_import_library_x86():
else:
log.warn('Cannot build import library: "%s" not found', lib_file)
return
- if os.path.isfile(out_file):
- log.debug('Skip building import library: "%s" exists', out_file)
- return
- # didn't find in virtualenv, try base distribution, too
- base_file = os.path.join(sys.base_prefix, 'libs', out_name)
- if os.path.isfile(base_file):
- log.debug('Skip building import library: "%s" exists', out_file)
- return
log.info('Building import library (ARCH=x86): "%s"', out_file)
from numpy.distutils import lib2def
@@ -456,9 +490,9 @@ def _build_import_library_x86():
dlist, flist = lib2def.parse_nm(nm_output)
lib2def.output_def(dlist, flist, lib2def.DEF_HEADER, open(def_file, 'w'))
- dll_name = "python%d%d.dll" % tuple(sys.version_info[:2])
+ dll_name = find_python_dll ()
args = (dll_name, def_file, out_file)
- cmd = 'dlltool --dllname %s --def %s --output-lib %s' % args
+ cmd = 'dlltool --dllname "%s" --def "%s" --output-lib "%s"' % args
status = os.system(cmd)
# for now, fail silently
if status:
diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py
index b8520aca2..0fba86589 100644
--- a/numpy/distutils/system_info.py
+++ b/numpy/distutils/system_info.py
@@ -1667,6 +1667,8 @@ class blas_info(system_info):
info = self.check_libs(lib_dirs, blas_libs, [])
if info is None:
return
+ else:
+ info['include_dirs'] = self.get_include_dirs()
if platform.system() == 'Windows':
# The check for windows is needed because has_cblas uses the
# same compiler that was used to compile Python and msvc is
diff --git a/numpy/distutils/tests/test_misc_util.py b/numpy/distutils/tests/test_misc_util.py
index 3e97b6fe2..f7fcbe224 100644
--- a/numpy/distutils/tests/test_misc_util.py
+++ b/numpy/distutils/tests/test_misc_util.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
from __future__ import division, absolute_import, print_function
from os.path import join, sep, dirname
diff --git a/numpy/doc/indexing.py b/numpy/doc/indexing.py
index 3e3e95641..39b2c73ed 100644
--- a/numpy/doc/indexing.py
+++ b/numpy/doc/indexing.py
@@ -200,8 +200,8 @@ one index array with y: ::
What results is the construction of a new array where each value of
the index array selects one row from the array being indexed and the
-resultant array has the resulting shape (size of row, number index
-elements).
+resultant array has the resulting shape (number of index elements,
+size of row).
An example of where this may be useful is for a color lookup table
where we want to map the values of an image into RGB triples for
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
index 2bdb21bb3..e38e8e3fe 100755
--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -2451,7 +2451,8 @@ def get_parameters(vars, global_params={}):
if not selected_kind_re.match(v):
v_ = v.split('_')
# In case there are additive parameters
- v = ''.join(v_[:-1]).lower().replace(v_[-1].lower(), '')
+ if len(v_) > 1:
+ v = ''.join(v_[:-1]).lower().replace(v_[-1].lower(), '')
# Currently this will not work for complex numbers.
# There is missing code for extracting a complex number,
diff --git a/numpy/f2py/tests/src/parameter/constant_compound.f90 b/numpy/f2py/tests/src/parameter/constant_compound.f90
new file mode 100644
index 000000000..e51f5e9b2
--- /dev/null
+++ b/numpy/f2py/tests/src/parameter/constant_compound.f90
@@ -0,0 +1,15 @@
+! Check that parameters are correct intercepted.
+! Constants with comma separations are commonly
+! used, for instance Pi = 3._dp
+subroutine foo_compound_int(x)
+ implicit none
+ integer, parameter :: ii = selected_int_kind(9)
+ integer(ii), intent(inout) :: x
+ dimension x(3)
+ integer(ii), parameter :: three = 3_ii
+ integer(ii), parameter :: two = 2_ii
+ integer(ii), parameter :: six = three * 1_ii * two
+
+ x(1) = x(1) + x(2) + x(3) * six
+ return
+end subroutine
diff --git a/numpy/f2py/tests/src/parameter/constant_non_compound.f90 b/numpy/f2py/tests/src/parameter/constant_non_compound.f90
new file mode 100644
index 000000000..62c9a5b94
--- /dev/null
+++ b/numpy/f2py/tests/src/parameter/constant_non_compound.f90
@@ -0,0 +1,23 @@
+! Check that parameters are correct intercepted.
+! Specifically that types of constants without
+! compound kind specs are correctly inferred
+! adapted Gibbs iteration code from pymc
+! for this test case
+subroutine foo_non_compound_int(x)
+ implicit none
+ integer, parameter :: ii = selected_int_kind(9)
+
+ integer(ii) maxiterates
+ parameter (maxiterates=2)
+
+ integer(ii) maxseries
+ parameter (maxseries=2)
+
+ integer(ii) wasize
+ parameter (wasize=maxiterates*maxseries)
+ integer(ii), intent(inout) :: x
+ dimension x(wasize)
+
+ x(1) = x(1) + x(2) + x(3) + x(4) * wasize
+ return
+end subroutine
diff --git a/numpy/f2py/tests/test_parameter.py b/numpy/f2py/tests/test_parameter.py
index f0168b2d5..b6891756d 100644
--- a/numpy/f2py/tests/test_parameter.py
+++ b/numpy/f2py/tests/test_parameter.py
@@ -18,6 +18,8 @@ class TestParameters(util.F2PyTest):
sources = [_path('src', 'parameter', 'constant_real.f90'),
_path('src', 'parameter', 'constant_integer.f90'),
_path('src', 'parameter', 'constant_both.f90'),
+ _path('src', 'parameter', 'constant_compound.f90'),
+ _path('src', 'parameter', 'constant_non_compound.f90'),
]
@dec.slow
@@ -43,6 +45,24 @@ class TestParameters(util.F2PyTest):
assert_equal(x, [0 + 1 + 2*3, 1, 2])
@dec.slow
+ def test_constant_compound_int(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.int32)[::2]
+ assert_raises(ValueError, self.module.foo_compound_int, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.int32)
+ self.module.foo_compound_int(x)
+ assert_equal(x, [0 + 1 + 2*6, 1, 2])
+
+ @dec.slow
+ def test_constant_non_compound_int(self):
+ # check values
+ x = np.arange(4, dtype=np.int32)
+ self.module.foo_non_compound_int(x)
+ assert_equal(x, [0 + 1 + 2 + 3*4, 1, 2, 3])
+
+ @dec.slow
def test_constant_integer_int(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.int32)[::2]
diff --git a/numpy/fft/fftpack.py b/numpy/fft/fftpack.py
index 7486ff51e..bd116b9cb 100644
--- a/numpy/fft/fftpack.py
+++ b/numpy/fft/fftpack.py
@@ -371,7 +371,9 @@ def rfft(a, n=None, axis=-1, norm=None):
output = _raw_fft(a, n, axis, fftpack.rffti, fftpack.rfftf,
_real_fft_cache)
if _unitary(norm):
- output *= 1 / sqrt(a.shape[axis])
+ if n is None:
+ n = a.shape[axis]
+ output *= 1 / sqrt(n)
return output
diff --git a/numpy/fft/tests/test_fftpack.py b/numpy/fft/tests/test_fftpack.py
index 2e6294252..a2cbc0f63 100644
--- a/numpy/fft/tests/test_fftpack.py
+++ b/numpy/fft/tests/test_fftpack.py
@@ -71,9 +71,13 @@ class TestFFT1D(TestCase):
def test_rfft(self):
x = random(30)
- assert_array_almost_equal(np.fft.fft(x)[:16], np.fft.rfft(x))
- assert_array_almost_equal(np.fft.rfft(x) / np.sqrt(30),
- np.fft.rfft(x, norm="ortho"))
+ for n in [x.size, 2*x.size]:
+ for norm in [None, 'ortho']:
+ assert_array_almost_equal(
+ np.fft.fft(x, n=n, norm=norm)[:(n//2 + 1)],
+ np.fft.rfft(x, n=n, norm=norm))
+ assert_array_almost_equal(np.fft.rfft(x, n=n) / np.sqrt(n),
+ np.fft.rfft(x, n=n, norm="ortho"))
def test_irfft(self):
x = random(30)
@@ -122,6 +126,24 @@ class TestFFT1D(TestCase):
x_herm, np.fft.ihfft(np.fft.hfft(x_herm, norm="ortho"),
norm="ortho"))
+ def test_all_1d_norm_preserving(self):
+ # verify that round-trip transforms are norm-preserving
+ x = random(30)
+ x_norm = np.linalg.norm(x)
+ n = x.size * 2
+ func_pairs = [(np.fft.fft, np.fft.ifft),
+ (np.fft.rfft, np.fft.irfft),
+ # hfft: order so the first function takes x.size samples
+ # (necessary for comparison to x_norm above)
+ (np.fft.ihfft, np.fft.hfft),
+ ]
+ for forw, back in func_pairs:
+ for n in [x.size, 2*x.size]:
+ for norm in [None, 'ortho']:
+ tmp = forw(x, n=n, norm=norm)
+ tmp = back(tmp, n=n, norm=norm)
+ assert_array_almost_equal(x_norm,
+ np.linalg.norm(tmp))
class TestFFTThreadSafe(TestCase):
threads = 16
diff --git a/numpy/fft/tests/test_helper.py b/numpy/fft/tests/test_helper.py
index cb85755d2..ff56ff63c 100644
--- a/numpy/fft/tests/test_helper.py
+++ b/numpy/fft/tests/test_helper.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
"""Test functions for fftpack.helper module
Copied from fftpack.helper by Pearu Peterson, October 2005
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index d01430c8c..ae1420b72 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -638,7 +638,7 @@ def histogram(a, bins=10, range=None, normed=False, weights=None,
>>> rng = np.random.RandomState(10) # deterministic random data
>>> a = np.hstack((rng.normal(size=1000),
... rng.normal(loc=5, scale=2, size=1000)))
- >>> plt.hist(a, bins='auto') # plt.hist passes it's arguments to np.histogram
+ >>> plt.hist(a, bins='auto') # plt.hist passes its arguments to np.histogram
>>> plt.title("Histogram with 'auto' bins")
>>> plt.show()
@@ -1027,9 +1027,16 @@ def average(a, axis=None, weights=None, returned=False):
a : array_like
Array containing data to be averaged. If `a` is not an array, a
conversion is attempted.
- axis : int, optional
- Axis along which to average `a`. If `None`, averaging is done over
- the flattened array.
+ axis : None or int or tuple of ints, optional
+ Axis or axes along which to average `a`. The default,
+ axis=None, will average over all of the elements of the input array.
+ If axis is negative it counts from the last to the first axis.
+
+ .. versionadded:: 1.7.0
+
+ If axis is a tuple of ints, averaging is performed on all of the axes
+ specified in the tuple instead of a single axis or all the axes as
+ before.
weights : array_like, optional
An array of weights associated with the values in `a`. Each value in
`a` contributes to the average according to its associated weight.
@@ -4498,24 +4505,21 @@ def meshgrid(*xi, **kwargs):
"Valid values for `indexing` are 'xy' and 'ij'.")
s0 = (1,) * ndim
- output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1::])
+ output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1:])
for i, x in enumerate(xi)]
- shape = [x.size for x in output]
-
if indexing == 'xy' and ndim > 1:
# switch first and second axis
- output[0].shape = (1, -1) + (1,)*(ndim - 2)
- output[1].shape = (-1, 1) + (1,)*(ndim - 2)
- shape[0], shape[1] = shape[1], shape[0]
+ output[0].shape = (1, -1) + s0[2:]
+ output[1].shape = (-1, 1) + s0[2:]
- if copy_:
- output = [x.copy() for x in output]
-
- if not sparse and len(output) > 0:
+ if not sparse:
# Return the full N-D matrix (not only the 1-D vector)
output = np.broadcast_arrays(*output, subok=True)
+ if copy_:
+ output = [x.copy() for x in output]
+
return output
diff --git a/numpy/lib/index_tricks.py b/numpy/lib/index_tricks.py
index a0875a25f..84c161b2e 100644
--- a/numpy/lib/index_tricks.py
+++ b/numpy/lib/index_tricks.py
@@ -41,6 +41,10 @@ def ix_(*args):
Parameters
----------
args : 1-D sequences
+ Each sequence should be of integer or boolean type.
+ Boolean sequences will be interpreted as boolean masks for the
+ corresponding dimension (equivalent to passing in
+ ``np.nonzero(boolean_sequence)``).
Returns
-------
@@ -58,7 +62,7 @@ def ix_(*args):
>>> a
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
- >>> ixgrid = np.ix_([0,1], [2,4])
+ >>> ixgrid = np.ix_([0, 1], [2, 4])
>>> ixgrid
(array([[0],
[1]]), array([[2, 4]]))
@@ -68,6 +72,15 @@ def ix_(*args):
array([[2, 4],
[7, 9]])
+ >>> ixgrid = np.ix_([True, True], [2, 4])
+ >>> a[ixgrid]
+ array([[2, 4],
+ [7, 9]])
+ >>> ixgrid = np.ix_([True, True], [False, False, True, False, True])
+ >>> a[ixgrid]
+ array([[2, 4],
+ [7, 9]])
+
"""
out = []
nd = len(args)
@@ -209,9 +222,6 @@ class nd_grid(object):
else:
return _nx.arange(start, stop, step)
- def __getslice__(self, i, j):
- return _nx.arange(i, j)
-
def __len__(self):
return 0
@@ -338,10 +348,6 @@ class AxisConcatenator(object):
res = _nx.concatenate(tuple(objs), axis=self.axis)
return self._retval(res)
- def __getslice__(self, i, j):
- res = _nx.arange(i, j)
- return self._retval(res)
-
def __len__(self):
return 0
@@ -665,8 +671,8 @@ s_ = IndexExpression(maketuple=False)
def fill_diagonal(a, val, wrap=False):
"""Fill the main diagonal of the given array of any dimensionality.
- For an array `a` with ``a.ndim > 2``, the diagonal is the list of
- locations with indices ``a[i, i, ..., i]`` all identical. This function
+ For an array `a` with ``a.ndim >= 2``, the diagonal is the list of
+ locations with indices ``a[i, ..., i]`` all identical. This function
modifies the input array in-place, it does not return a value.
Parameters
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
index 13eb5cefc..c575cc030 100644
--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -603,18 +603,56 @@ def savez_compressed(file, *args, **kwds):
Parameters
----------
- file : str
- File name of ``.npz`` file.
- args : Arguments
- Function arguments.
- kwds : Keyword arguments
- Keywords.
+ file : str or file
+ Either the file name (string) or an open file (file-like object)
+ where the data will be saved. If file is a string or a Path, the
+ ``.npz`` extension will be appended to the file name if it is not
+ already there.
+ args : Arguments, optional
+ Arrays to save to the file. Since it is not possible for Python to
+ know the names of the arrays outside `savez`, the arrays will be saved
+ with names "arr_0", "arr_1", and so on. These arguments can be any
+ expression.
+ kwds : Keyword arguments, optional
+ Arrays to save to the file. Arrays will be saved in the file with the
+ keyword names.
+
+ Returns
+ -------
+ None
See Also
--------
+ numpy.save : Save a single array to a binary file in NumPy format.
+ numpy.savetxt : Save an array to a file as plain text.
numpy.savez : Save several arrays into an uncompressed ``.npz`` file format
numpy.load : Load the files created by savez_compressed.
+ Notes
+ -----
+ The ``.npz`` file format is a zipped archive of files named after the
+ variables they contain. The archive is compressed with
+ ``zipfile.ZIP_DEFLATED`` and each file in the archive contains one variable
+ in ``.npy`` format. For a description of the ``.npy`` format, see
+ `numpy.lib.format` or the NumPy Enhancement Proposal
+ http://docs.scipy.org/doc/numpy/neps/npy-format.html
+
+ When opening the saved ``.npz`` file with `load` a `NpzFile` object is
+ returned. This is a dictionary-like object which can be queried for
+ its list of arrays (with the ``.files`` attribute), and for the arrays
+ themselves.
+
+ Examples
+ --------
+ >>> test_array = np.random.rand(3, 2)
+ >>> test_vector = np.random.rand(4)
+ >>> np.savez_compressed('/tmp/123', a=test_array, b=test_vector)
+ >>> loaded = np.load('/tmp/123.npz')
+ >>> print(np.array_equal(test_array, loaded['a']))
+ True
+ >>> print(np.array_equal(test_vector, loaded['b']))
+ True
+
"""
_savez(file, args, kwds, True)
diff --git a/numpy/lib/shape_base.py b/numpy/lib/shape_base.py
index e580690d1..58e13533b 100644
--- a/numpy/lib/shape_base.py
+++ b/numpy/lib/shape_base.py
@@ -6,8 +6,10 @@ import numpy.core.numeric as _nx
from numpy.core.numeric import (
asarray, zeros, outer, concatenate, isscalar, array, asanyarray
)
-from numpy.core.fromnumeric import product, reshape
+from numpy.core.fromnumeric import product, reshape, transpose
from numpy.core import vstack, atleast_3d
+from numpy.lib.index_tricks import ndindex
+from numpy.matrixlib.defmatrix import matrix # this raises all the right alarm bells
__all__ = [
@@ -45,9 +47,10 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
-------
apply_along_axis : ndarray
The output array. The shape of `outarr` is identical to the shape of
- `arr`, except along the `axis` dimension, where the length of `outarr`
- is equal to the size of the return value of `func1d`. If `func1d`
- returns a scalar `outarr` will have one fewer dimensions than `arr`.
+ `arr`, except along the `axis` dimension. This axis is removed, and
+ replaced with new dimensions equal to the shape of the return value
+ of `func1d`. So if `func1d` returns a scalar `outarr` will have one
+ fewer dimensions than `arr`.
See Also
--------
@@ -64,7 +67,7 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
>>> np.apply_along_axis(my_func, 1, b)
array([ 2., 5., 8.])
- For a function that doesn't return a scalar, the number of dimensions in
+ For a function that returns a 1D array, the number of dimensions in
`outarr` is the same as `arr`.
>>> b = np.array([[8,1,7], [4,3,9], [5,2,6]])
@@ -73,66 +76,79 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
[3, 4, 9],
[2, 5, 6]])
+ For a function that returns a higher dimensional array, those dimensions
+ are inserted in place of the `axis` dimension.
+
+ >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
+ >>> np.apply_along_axis(np.diag, -1, b)
+ array([[[1, 0, 0],
+ [0, 2, 0],
+ [0, 0, 3]],
+
+ [[4, 0, 0],
+ [0, 5, 0],
+ [0, 0, 6]],
+
+ [[7, 0, 0],
+ [0, 8, 0],
+ [0, 0, 9]]])
"""
+ # handle negative axes
arr = asanyarray(arr)
nd = arr.ndim
+ if not (-nd <= axis < nd):
+ raise IndexError('axis {0} out of bounds [-{1}, {1})'.format(axis, nd))
if axis < 0:
axis += nd
- if (axis >= nd):
- raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d."
- % (axis, nd))
- ind = [0]*(nd-1)
- i = zeros(nd, 'O')
- indlist = list(range(nd))
- indlist.remove(axis)
- i[axis] = slice(None, None)
- outshape = asarray(arr.shape).take(indlist)
- i.put(indlist, ind)
- res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
- # if res is a number, then we have a smaller output array
- if isscalar(res):
- outarr = zeros(outshape, asarray(res).dtype)
- outarr[tuple(ind)] = res
- Ntot = product(outshape)
- k = 1
- while k < Ntot:
- # increment the index
- ind[-1] += 1
- n = -1
- while (ind[n] >= outshape[n]) and (n > (1-nd)):
- ind[n-1] += 1
- ind[n] = 0
- n -= 1
- i.put(indlist, ind)
- res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
- outarr[tuple(ind)] = res
- k += 1
- return outarr
+
+ # arr, with the iteration axis at the end
+ in_dims = list(range(nd))
+ inarr_view = transpose(arr, in_dims[:axis] + in_dims[axis+1:] + [axis])
+
+ # compute indices for the iteration axes
+ inds = ndindex(inarr_view.shape[:-1])
+
+ # invoke the function on the first item
+ try:
+ ind0 = next(inds)
+ except StopIteration:
+ raise ValueError('Cannot apply_along_axis when any iteration dimensions are 0')
+ res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs))
+
+ # build a buffer for storing evaluations of func1d.
+ # remove the requested axis, and add the new ones on the end.
+ # laid out so that each write is contiguous.
+ # for a tuple index inds, buff[inds] = func1d(inarr_view[inds])
+ buff = zeros(inarr_view.shape[:-1] + res.shape, res.dtype)
+
+ # permutation of axes such that out = buff.transpose(buff_permute)
+ buff_dims = list(range(buff.ndim))
+ buff_permute = (
+ buff_dims[0 : axis] +
+ buff_dims[buff.ndim-res.ndim : buff.ndim] +
+ buff_dims[axis : buff.ndim-res.ndim]
+ )
+
+ # matrices have a nasty __array_prepare__ and __array_wrap__
+ if not isinstance(res, matrix):
+ buff = res.__array_prepare__(buff)
+
+ # save the first result, then compute and save all remaining results
+ buff[ind0] = res
+ for ind in inds:
+ buff[ind] = asanyarray(func1d(inarr_view[ind], *args, **kwargs))
+
+ if not isinstance(res, matrix):
+ # wrap the array, to preserve subclasses
+ buff = res.__array_wrap__(buff)
+
+ # finally, rotate the inserted axes back to where they belong
+ return transpose(buff, buff_permute)
+
else:
- res = asanyarray(res)
- Ntot = product(outshape)
- holdshape = outshape
- outshape = list(arr.shape)
- outshape[axis] = res.size
- outarr = zeros(outshape, res.dtype)
- outarr = res.__array_wrap__(outarr)
- outarr[tuple(i.tolist())] = res
- k = 1
- while k < Ntot:
- # increment the index
- ind[-1] += 1
- n = -1
- while (ind[n] >= holdshape[n]) and (n > (1-nd)):
- ind[n-1] += 1
- ind[n] = 0
- n -= 1
- i.put(indlist, ind)
- res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
- outarr[tuple(i.tolist())] = res
- k += 1
- if res.shape == ():
- outarr = outarr.squeeze(axis)
- return outarr
+ # matrices have to be transposed first, because they collapse dimensions!
+ out_arr = transpose(buff, buff_permute)
+ return res.__array_wrap__(out_arr)
def apply_over_axes(func, a, axes):
diff --git a/numpy/lib/stride_tricks.py b/numpy/lib/stride_tricks.py
index f390cf49b..545623c38 100644
--- a/numpy/lib/stride_tricks.py
+++ b/numpy/lib/stride_tricks.py
@@ -179,7 +179,7 @@ def _broadcast_shape(*args):
supplied arrays against each other.
"""
if not args:
- raise ValueError('must provide at least one argument')
+ return ()
# use the old-iterator because np.nditer does not handle size 0 arrays
# consistently
b = np.broadcast(*args[:32])
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index 5c2446e50..f69c24d59 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -2266,6 +2266,16 @@ class TestMeshgrid(TestCase):
assert_(X.dtype == x.dtype)
assert_(Y.dtype == y.dtype)
+ def test_writeback(self):
+ # Issue 8561
+ X = np.array([1.1, 2.2])
+ Y = np.array([3.3, 4.4])
+ x, y = np.meshgrid(X, Y, sparse=False, copy=True)
+
+ x[0, :] = 0
+ assert_equal(x[0, :], 0)
+ assert_equal(x[1, :], X)
+
class TestPiecewise(TestCase):
diff --git a/numpy/lib/tests/test_nanfunctions.py b/numpy/lib/tests/test_nanfunctions.py
index e1942338b..2b310457b 100644
--- a/numpy/lib/tests/test_nanfunctions.py
+++ b/numpy/lib/tests/test_nanfunctions.py
@@ -710,6 +710,18 @@ class TestNanFunctions_Median(TestCase):
a = np.array([[inf, inf], [inf, inf]])
assert_equal(np.nanmedian(a, axis=1), inf)
+ a = np.array([[inf, 7, -inf, -9],
+ [-10, np.nan, np.nan, 5],
+ [4, np.nan, np.nan, inf]],
+ dtype=np.float32)
+ if inf > 0:
+ assert_equal(np.nanmedian(a, axis=0), [4., 7., -inf, 5.])
+ assert_equal(np.nanmedian(a), 4.5)
+ else:
+ assert_equal(np.nanmedian(a, axis=0), [-10., 7., -inf, -9.])
+ assert_equal(np.nanmedian(a), -2.5)
+ assert_equal(np.nanmedian(a, axis=-1), [-1., -2.5, inf])
+
for i in range(0, 10):
for j in range(1, 10):
a = np.array([([np.nan] * i) + ([inf] * j)] * 2)
diff --git a/numpy/lib/tests/test_packbits.py b/numpy/lib/tests/test_packbits.py
index 5d8ac861b..965cbf67c 100644
--- a/numpy/lib/tests/test_packbits.py
+++ b/numpy/lib/tests/test_packbits.py
@@ -1,7 +1,9 @@
from __future__ import division, absolute_import, print_function
import numpy as np
-from numpy.testing import assert_array_equal, assert_equal, assert_raises
+from numpy.testing import (
+ assert_array_equal, assert_equal, assert_raises, run_module_suite
+)
def test_packbits():
@@ -51,6 +53,175 @@ def test_packbits_empty_with_axis():
assert_equal(b.shape, out_shape)
+def test_packbits_large():
+ # test data large enough for 16 byte vectorization
+ a = np.array([1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1,
+ 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1,
+ 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0,
+ 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1,
+ 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0])
+ a = a.repeat(3)
+ for dtype in '?bBhHiIlLqQ':
+ arr = np.array(a, dtype=dtype)
+ b = np.packbits(arr, axis=None)
+ assert_equal(b.dtype, np.uint8)
+ r = [252, 127, 192, 3, 254, 7, 252, 0, 7, 31, 240, 0, 28, 1, 255, 252,
+ 113, 248, 3, 255, 192, 28, 15, 192, 28, 126, 0, 224, 127, 255,
+ 227, 142, 7, 31, 142, 63, 28, 126, 56, 227, 240, 0, 227, 128, 63,
+ 224, 14, 56, 252, 112, 56, 255, 241, 248, 3, 240, 56, 224, 112,
+ 63, 255, 255, 199, 224, 14, 0, 31, 143, 192, 3, 255, 199, 0, 1,
+ 255, 224, 1, 255, 252, 126, 63, 0, 1, 192, 252, 14, 63, 0, 15,
+ 199, 252, 113, 255, 3, 128, 56, 252, 14, 7, 0, 113, 255, 255, 142, 56, 227,
+ 129, 248, 227, 129, 199, 31, 128]
+ assert_array_equal(b, r)
+ # equal for size being multiple of 8
+ assert_array_equal(np.unpackbits(b)[:-4], a)
+
+ # check last byte of different remainders (16 byte vectorization)
+ b = [np.packbits(arr[:-i], axis=None)[-1] for i in range(1, 16)]
+ assert_array_equal(b, [128, 128, 128, 31, 30, 28, 24, 16, 0, 0, 0, 199,
+ 198, 196, 192])
+
+
+ arr = arr.reshape(36, 25)
+ b = np.packbits(arr, axis=0)
+ assert_equal(b.dtype, np.uint8)
+ assert_array_equal(b, [[190, 186, 178, 178, 150, 215, 87, 83, 83, 195,
+ 199, 206, 204, 204, 140, 140, 136, 136, 8, 40, 105,
+ 107, 75, 74, 88],
+ [72, 216, 248, 241, 227, 195, 202, 90, 90, 83,
+ 83, 119, 127, 109, 73, 64, 208, 244, 189, 45,
+ 41, 104, 122, 90, 18],
+ [113, 120, 248, 216, 152, 24, 60, 52, 182, 150,
+ 150, 150, 146, 210, 210, 246, 255, 255, 223,
+ 151, 21, 17, 17, 131, 163],
+ [214, 210, 210, 64, 68, 5, 5, 1, 72, 88, 92,
+ 92, 78, 110, 39, 181, 149, 220, 222, 218, 218,
+ 202, 234, 170, 168],
+ [0, 128, 128, 192, 80, 112, 48, 160, 160, 224,
+ 240, 208, 144, 128, 160, 224, 240, 208, 144,
+ 144, 176, 240, 224, 192, 128]])
+
+ b = np.packbits(arr, axis=1)
+ assert_equal(b.dtype, np.uint8)
+ assert_array_equal(b, [[252, 127, 192, 0],
+ [ 7, 252, 15, 128],
+ [240, 0, 28, 0],
+ [255, 128, 0, 128],
+ [192, 31, 255, 128],
+ [142, 63, 0, 0],
+ [255, 240, 7, 0],
+ [ 7, 224, 14, 0],
+ [126, 0, 224, 0],
+ [255, 255, 199, 0],
+ [ 56, 28, 126, 0],
+ [113, 248, 227, 128],
+ [227, 142, 63, 0],
+ [ 0, 28, 112, 0],
+ [ 15, 248, 3, 128],
+ [ 28, 126, 56, 0],
+ [ 56, 255, 241, 128],
+ [240, 7, 224, 0],
+ [227, 129, 192, 128],
+ [255, 255, 254, 0],
+ [126, 0, 224, 0],
+ [ 3, 241, 248, 0],
+ [ 0, 255, 241, 128],
+ [128, 0, 255, 128],
+ [224, 1, 255, 128],
+ [248, 252, 126, 0],
+ [ 0, 7, 3, 128],
+ [224, 113, 248, 0],
+ [ 0, 252, 127, 128],
+ [142, 63, 224, 0],
+ [224, 14, 63, 0],
+ [ 7, 3, 128, 0],
+ [113, 255, 255, 128],
+ [ 28, 113, 199, 0],
+ [ 7, 227, 142, 0],
+ [ 14, 56, 252, 0]])
+
+ arr = arr.T.copy()
+ b = np.packbits(arr, axis=0)
+ assert_equal(b.dtype, np.uint8)
+ assert_array_equal(b, [[252, 7, 240, 255, 192, 142, 255, 7, 126, 255,
+ 56, 113, 227, 0, 15, 28, 56, 240, 227, 255,
+ 126, 3, 0, 128, 224, 248, 0, 224, 0, 142, 224,
+ 7, 113, 28, 7, 14],
+ [127, 252, 0, 128, 31, 63, 240, 224, 0, 255,
+ 28, 248, 142, 28, 248, 126, 255, 7, 129, 255,
+ 0, 241, 255, 0, 1, 252, 7, 113, 252, 63, 14,
+ 3, 255, 113, 227, 56],
+ [192, 15, 28, 0, 255, 0, 7, 14, 224, 199, 126,
+ 227, 63, 112, 3, 56, 241, 224, 192, 254, 224,
+ 248, 241, 255, 255, 126, 3, 248, 127, 224, 63,
+ 128, 255, 199, 142, 252],
+ [0, 128, 0, 128, 128, 0, 0, 0, 0, 0, 0, 128, 0,
+ 0, 128, 0, 128, 0, 128, 0, 0, 0, 128, 128,
+ 128, 0, 128, 0, 128, 0, 0, 0, 128, 0, 0, 0]])
+
+ b = np.packbits(arr, axis=1)
+ assert_equal(b.dtype, np.uint8)
+ assert_array_equal(b, [[190, 72, 113, 214, 0],
+ [186, 216, 120, 210, 128],
+ [178, 248, 248, 210, 128],
+ [178, 241, 216, 64, 192],
+ [150, 227, 152, 68, 80],
+ [215, 195, 24, 5, 112],
+ [ 87, 202, 60, 5, 48],
+ [ 83, 90, 52, 1, 160],
+ [ 83, 90, 182, 72, 160],
+ [195, 83, 150, 88, 224],
+ [199, 83, 150, 92, 240],
+ [206, 119, 150, 92, 208],
+ [204, 127, 146, 78, 144],
+ [204, 109, 210, 110, 128],
+ [140, 73, 210, 39, 160],
+ [140, 64, 246, 181, 224],
+ [136, 208, 255, 149, 240],
+ [136, 244, 255, 220, 208],
+ [ 8, 189, 223, 222, 144],
+ [ 40, 45, 151, 218, 144],
+ [105, 41, 21, 218, 176],
+ [107, 104, 17, 202, 240],
+ [ 75, 122, 17, 234, 224],
+ [ 74, 90, 131, 170, 192],
+ [ 88, 18, 163, 168, 128]])
+
+
+ # result is the same if input is multiplied with a nonzero value
+ for dtype in 'bBhHiIlLqQ':
+ arr = np.array(a, dtype=dtype)
+ rnd = np.random.randint(low=np.iinfo(dtype).min,
+ high=np.iinfo(dtype).max, size=arr.size,
+ dtype=dtype)
+ rnd[rnd == 0] = 1
+ arr *= rnd.astype(dtype)
+ b = np.packbits(arr, axis=-1)
+ assert_array_equal(np.unpackbits(b)[:-4], a)
+
+ assert_raises(TypeError, np.packbits, np.array(a, dtype=float))
+
+
+def test_packbits_very_large():
+ # test some with a larger arrays gh-8637
+ # code is covered earlier but larger array makes crash on bug more likely
+ for s in range(950, 1050):
+ for dt in '?bBhHiIlLqQ':
+ x = np.ones((200, s), dtype=bool)
+ np.packbits(x, axis=1)
+
+
def test_unpackbits():
# Copied from the docstring.
a = np.array([[2], [7], [23]], dtype=np.uint8)
@@ -86,3 +257,18 @@ def test_unpackbits_empty_with_axis():
b = np.unpackbits(a, axis=ax)
assert_equal(b.dtype, np.uint8)
assert_equal(b.shape, out_shape)
+
+
+def test_unpackbits_large():
+ # test all possible numbers via comparison to already tested packbits
+ d = np.arange(277, dtype=np.uint8)
+ assert_array_equal(np.packbits(np.unpackbits(d)), d)
+ assert_array_equal(np.packbits(np.unpackbits(d[::2])), d[::2])
+ d = np.tile(d, (3, 1))
+ assert_array_equal(np.packbits(np.unpackbits(d, axis=1), axis=1), d)
+ d = d.T.copy()
+ assert_array_equal(np.packbits(np.unpackbits(d, axis=0), axis=0), d)
+
+
+if __name__ == "__main__":
+ run_module_suite()
diff --git a/numpy/lib/tests/test_shape_base.py b/numpy/lib/tests/test_shape_base.py
index 2eb4a809d..8bdf3d3da 100644
--- a/numpy/lib/tests/test_shape_base.py
+++ b/numpy/lib/tests/test_shape_base.py
@@ -28,14 +28,20 @@ class TestApplyAlongAxis(TestCase):
[[27, 30, 33], [36, 39, 42], [45, 48, 51]])
def test_preserve_subclass(self):
+ # this test is particularly malicious because matrix
+ # refuses to become 1d
def double(row):
return row * 2
m = np.matrix([[0, 1], [2, 3]])
+ expected = np.matrix([[0, 2], [4, 6]])
+
result = apply_along_axis(double, 0, m)
- assert isinstance(result, np.matrix)
- assert_array_equal(
- result, np.matrix([[0, 2], [4, 6]])
- )
+ assert_(isinstance(result, np.matrix))
+ assert_array_equal(result, expected)
+
+ result = apply_along_axis(double, 1, m)
+ assert_(isinstance(result, np.matrix))
+ assert_array_equal(result, expected)
def test_subclass(self):
class MinimalSubclass(np.ndarray):
@@ -50,13 +56,108 @@ class TestApplyAlongAxis(TestCase):
apply_along_axis(minimal_function, 0, a), np.array([1, 1, 1])
)
- def test_scalar_array(self):
+ def test_scalar_array(self, cls=np.ndarray):
+ a = np.ones((6, 3)).view(cls)
+ res = apply_along_axis(np.sum, 0, a)
+ assert_(isinstance(res, cls))
+ assert_array_equal(res, np.array([6, 6, 6]).view(cls))
+
+ def test_0d_array(self, cls=np.ndarray):
+ def sum_to_0d(x):
+ """ Sum x, returning a 0d array of the same class """
+ assert_equal(x.ndim, 1)
+ return np.squeeze(np.sum(x, keepdims=True))
+ a = np.ones((6, 3)).view(cls)
+ res = apply_along_axis(sum_to_0d, 0, a)
+ assert_(isinstance(res, cls))
+ assert_array_equal(res, np.array([6, 6, 6]).view(cls))
+
+ res = apply_along_axis(sum_to_0d, 1, a)
+ assert_(isinstance(res, cls))
+ assert_array_equal(res, np.array([3, 3, 3, 3, 3, 3]).view(cls))
+
+ def test_axis_insertion(self, cls=np.ndarray):
+ def f1to2(x):
+ """produces an assymmetric non-square matrix from x"""
+ assert_equal(x.ndim, 1)
+ return (x[::-1] * x[1:,None]).view(cls)
+
+ a2d = np.arange(6*3).reshape((6, 3))
+
+ # 2d insertion along first axis
+ actual = apply_along_axis(f1to2, 0, a2d)
+ expected = np.stack([
+ f1to2(a2d[:,i]) for i in range(a2d.shape[1])
+ ], axis=-1).view(cls)
+ assert_equal(type(actual), type(expected))
+ assert_equal(actual, expected)
+
+ # 2d insertion along last axis
+ actual = apply_along_axis(f1to2, 1, a2d)
+ expected = np.stack([
+ f1to2(a2d[i,:]) for i in range(a2d.shape[0])
+ ], axis=0).view(cls)
+ assert_equal(type(actual), type(expected))
+ assert_equal(actual, expected)
+
+ # 3d insertion along middle axis
+ a3d = np.arange(6*5*3).reshape((6, 5, 3))
+
+ actual = apply_along_axis(f1to2, 1, a3d)
+ expected = np.stack([
+ np.stack([
+ f1to2(a3d[i,:,j]) for i in range(a3d.shape[0])
+ ], axis=0)
+ for j in range(a3d.shape[2])
+ ], axis=-1).view(cls)
+ assert_equal(type(actual), type(expected))
+ assert_equal(actual, expected)
+
+ def test_subclass_preservation(self):
class MinimalSubclass(np.ndarray):
pass
- a = np.ones((6, 3)).view(MinimalSubclass)
- res = apply_along_axis(np.sum, 0, a)
- assert isinstance(res, MinimalSubclass)
- assert_array_equal(res, np.array([6, 6, 6]).view(MinimalSubclass))
+ self.test_scalar_array(MinimalSubclass)
+ self.test_0d_array(MinimalSubclass)
+ self.test_axis_insertion(MinimalSubclass)
+
+ def test_axis_insertion_ma(self):
+ def f1to2(x):
+ """produces an assymmetric non-square matrix from x"""
+ assert_equal(x.ndim, 1)
+ res = x[::-1] * x[1:,None]
+ return np.ma.masked_where(res%5==0, res)
+ a = np.arange(6*3).reshape((6, 3))
+ res = apply_along_axis(f1to2, 0, a)
+ assert_(isinstance(res, np.ma.masked_array))
+ assert_equal(res.ndim, 3)
+ assert_array_equal(res[:,:,0].mask, f1to2(a[:,0]).mask)
+ assert_array_equal(res[:,:,1].mask, f1to2(a[:,1]).mask)
+ assert_array_equal(res[:,:,2].mask, f1to2(a[:,2]).mask)
+
+ def test_tuple_func1d(self):
+ def sample_1d(x):
+ return x[1], x[0]
+ res = np.apply_along_axis(sample_1d, 1, np.array([[1, 2], [3, 4]]))
+ assert_array_equal(res, np.array([[2, 1], [4, 3]]))
+
+ def test_empty(self):
+ # can't apply_along_axis when there's no chance to call the function
+ def never_call(x):
+ assert_(False) # should never be reached
+
+ a = np.empty((0, 0))
+ assert_raises(ValueError, np.apply_along_axis, never_call, 0, a)
+ assert_raises(ValueError, np.apply_along_axis, never_call, 1, a)
+
+ # but it's sometimes ok with some non-zero dimensions
+ def empty_to_1(x):
+ assert_(len(x) == 0)
+ return 1
+
+ a = np.empty((10, 0))
+ actual = np.apply_along_axis(empty_to_1, 1, a)
+ assert_equal(actual, np.ones(10))
+ assert_raises(ValueError, np.apply_along_axis, empty_to_1, 0, a)
class TestApplyOverAxes(TestCase):
diff --git a/numpy/lib/tests/test_stride_tricks.py b/numpy/lib/tests/test_stride_tricks.py
index 95df135cf..39a76c2f6 100644
--- a/numpy/lib/tests/test_stride_tricks.py
+++ b/numpy/lib/tests/test_stride_tricks.py
@@ -266,7 +266,7 @@ def test_broadcast_to_raises():
def test_broadcast_shape():
# broadcast_shape is already exercized indirectly by broadcast_arrays
- assert_raises(ValueError, _broadcast_shape)
+ assert_equal(_broadcast_shape(), ())
assert_equal(_broadcast_shape([1, 2]), (2,))
assert_equal(_broadcast_shape(np.ones((1, 1))), (1, 1))
assert_equal(_broadcast_shape(np.ones((1, 1)), np.ones((3, 4))), (3, 4))
diff --git a/numpy/lib/tests/test_type_check.py b/numpy/lib/tests/test_type_check.py
index 93a4da97a..4523e3f24 100644
--- a/numpy/lib/tests/test_type_check.py
+++ b/numpy/lib/tests/test_type_check.py
@@ -183,6 +183,15 @@ class TestIscomplexobj(TestCase):
dummy = DummyPd()
assert_(iscomplexobj(dummy))
+ def test_custom_dtype_duck(self):
+ class MyArray(list):
+ @property
+ def dtype(self):
+ return complex
+
+ a = MyArray([1+0j, 2+0j, 3+0j])
+ assert_(iscomplexobj(a))
+
class TestIsrealobj(TestCase):
def test_basic(self):
diff --git a/numpy/lib/type_check.py b/numpy/lib/type_check.py
index 1658f160c..3bbee0258 100644
--- a/numpy/lib/type_check.py
+++ b/numpy/lib/type_check.py
@@ -268,12 +268,10 @@ def iscomplexobj(x):
"""
try:
dtype = x.dtype
+ type_ = dtype.type
except AttributeError:
- dtype = asarray(x).dtype
- try:
- return issubclass(dtype.type, _nx.complexfloating)
- except AttributeError:
- return False
+ type_ = asarray(x).dtype.type
+ return issubclass(type_, _nx.complexfloating)
def isrealobj(x):
diff --git a/numpy/lib/user_array.py b/numpy/lib/user_array.py
index 3103da57b..62398fc3c 100644
--- a/numpy/lib/user_array.py
+++ b/numpy/lib/user_array.py
@@ -51,15 +51,9 @@ class container(object):
def __getitem__(self, index):
return self._rc(self.array[index])
- def __getslice__(self, i, j):
- return self._rc(self.array[i:j])
-
def __setitem__(self, index, value):
self.array[index] = asarray(value, self.dtype)
- def __setslice__(self, i, j, value):
- self.array[i:j] = asarray(value, self.dtype)
-
def __abs__(self):
return self._rc(absolute(self.array))
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 4466dc0af..a6f474b95 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -2299,7 +2299,7 @@ def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True):
if issubclass(xnew.dtype.type, np.floating):
condition = umath.less_equal(
mabs(xnew - value), atol + rtol * mabs(value))
- mask = getattr(x, '_mask', nomask)
+ mask = getmask(x)
else:
condition = umath.equal(xnew, value)
mask = nomask
@@ -2948,10 +2948,9 @@ class MaskedArray(ndarray):
# XX: This looks like a bug -- shouldn't it check self.dtype
# instead?
if obj.dtype.names:
- _mask = getattr(obj, '_mask',
- make_mask_none(obj.shape, obj.dtype))
+ _mask = getmaskarray(obj)
else:
- _mask = getattr(obj, '_mask', nomask)
+ _mask = getmask(obj)
# If self and obj point to exactly the same data, then probably
# self is a simple view of obj (e.g., self = obj[...]), so they
@@ -2988,8 +2987,11 @@ class MaskedArray(ndarray):
Wraps the numpy array and sets the mask according to context.
"""
- result = obj.view(type(self))
- result._update_from(self)
+ if obj is self: # for in-place operations
+ result = obj
+ else:
+ result = obj.view(type(self))
+ result._update_from(self)
if context is not None:
result._mask = result._mask.copy()
@@ -3017,7 +3019,7 @@ class MaskedArray(ndarray):
except KeyError:
# Domain not recognized, use fill_value instead
fill_value = self.fill_value
- result = result.copy()
+
np.copyto(result, fill_value, where=d)
# Update the mask
@@ -3028,7 +3030,7 @@ class MaskedArray(ndarray):
m = (m | d)
# Make sure the mask has the proper size
- if result.shape == () and m:
+ if result is not self and result.shape == () and m:
return masked
else:
result._mask = m
@@ -3104,7 +3106,7 @@ class MaskedArray(ndarray):
# also make the mask be a view (so attr changes to the view's
# mask do no affect original object's mask)
# (especially important to avoid affecting np.masked singleton)
- if (getattr(output, '_mask', nomask) is not nomask):
+ if (getmask(output) is not nomask):
output._mask = output._mask.view()
# Make sure to reset the _fill_value if needed
@@ -3264,9 +3266,9 @@ class MaskedArray(ndarray):
return
# Get the _data part of the new value
- dval = value
+ dval = getattr(value, '_data', value)
# Get the _mask part of the new value
- mval = getattr(value, '_mask', nomask)
+ mval = getmask(value)
if nbfields and mval is nomask:
mval = tuple([False] * nbfields)
if _mask is nomask:
@@ -3328,26 +3330,6 @@ class MaskedArray(ndarray):
except (AttributeError, TypeError):
pass
- def __getslice__(self, i, j):
- """
- x.__getslice__(i, j) <==> x[i:j]
-
- Return the slice described by (i, j). The use of negative indices
- is not supported.
-
- """
- return self.__getitem__(slice(i, j))
-
- def __setslice__(self, i, j, value):
- """
- x.__setslice__(i, j, value) <==> x[i:j]=value
-
- Set the slice (i,j) of a to value. If value is masked, mask those
- locations.
-
- """
- self.__setitem__(slice(i, j), value)
-
def __setmask__(self, mask, copy=False):
"""
Set the mask.
@@ -3897,7 +3879,7 @@ class MaskedArray(ndarray):
"""
if self is masked:
return masked
- omask = getattr(other, '_mask', nomask)
+ omask = getmask(other)
if omask is nomask:
check = self.filled(0).__eq__(other)
try:
@@ -3933,7 +3915,7 @@ class MaskedArray(ndarray):
"""
if self is masked:
return masked
- omask = getattr(other, '_mask', nomask)
+ omask = getmask(other)
if omask is nomask:
check = self.filled(0).__ne__(other)
try:
@@ -4910,7 +4892,7 @@ class MaskedArray(ndarray):
# Explicit output
result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs)
if isinstance(out, MaskedArray):
- outmask = getattr(out, '_mask', nomask)
+ outmask = getmask(out)
if (outmask is nomask):
outmask = out._mask = make_mask_none(out.shape)
outmask.flat = newmask
@@ -4989,7 +4971,7 @@ class MaskedArray(ndarray):
# Explicit output
result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs)
if isinstance(out, MaskedArray):
- outmask = getattr(out, '_mask', nomask)
+ outmask = getmask(out)
if (outmask is nomask):
outmask = out._mask = make_mask_none(out.shape)
outmask.flat = newmask
@@ -5068,10 +5050,10 @@ class MaskedArray(ndarray):
if out is not None:
out.flat = result
if isinstance(out, MaskedArray):
- outmask = getattr(out, '_mask', nomask)
+ outmask = getmask(out)
if (outmask is nomask):
outmask = out._mask = make_mask_none(out.shape)
- outmask.flat = getattr(result, '_mask', nomask)
+ outmask.flat = getmask(result)
return out
return result
@@ -5154,7 +5136,7 @@ class MaskedArray(ndarray):
if dvar.ndim:
dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0))
dvar._update_from(self)
- elif getattr(dvar, '_mask', False):
+ elif getmask(dvar):
# Make sure that masked is returned when the scalar is masked.
dvar = masked
if out is not None:
@@ -5507,7 +5489,7 @@ class MaskedArray(ndarray):
# Explicit output
result = self.filled(fill_value).min(axis=axis, out=out, **kwargs)
if isinstance(out, MaskedArray):
- outmask = getattr(out, '_mask', nomask)
+ outmask = getmask(out)
if (outmask is nomask):
outmask = out._mask = make_mask_none(out.shape)
outmask.flat = newmask
@@ -5609,7 +5591,7 @@ class MaskedArray(ndarray):
# Explicit output
result = self.filled(fill_value).max(axis=axis, out=out, **kwargs)
if isinstance(out, MaskedArray):
- outmask = getattr(out, '_mask', nomask)
+ outmask = getmask(out)
if (outmask is nomask):
outmask = out._mask = make_mask_none(out.shape)
outmask.flat = newmask
@@ -5661,7 +5643,7 @@ class MaskedArray(ndarray):
(_data, _mask) = (self._data, self._mask)
cls = type(self)
# Make sure the indices are not masked
- maskindices = getattr(indices, '_mask', nomask)
+ maskindices = getmask(indices)
if maskindices is not nomask:
indices = indices.filled(0)
# Get the data, promoting scalars to 0d arrays with [...] so that
@@ -6130,8 +6112,11 @@ class MaskedConstant(MaskedArray):
def __array_finalize__(self, obj):
return
- def __array_wrap__(self, obj):
- return self
+ def __array_prepare__(self, obj, context=None):
+ return self.view(MaskedArray).__array_prepare__(obj, context)
+
+ def __array_wrap__(self, obj, context=None):
+ return self.view(MaskedArray).__array_wrap__(obj, context)
def __str__(self):
return str(masked_print_option._display)
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index 1774ece30..29a15633d 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -729,10 +729,6 @@ def _median(a, axis=None, out=None, overwrite_input=False):
s = mid.sum(out=out)
if not odd:
s = np.true_divide(s, 2., casting='safe', out=out)
- # masked ufuncs do not fullfill `returned is out` (gh-8416)
- # fix this to return the same in the nd path
- if out is not None:
- s = out
s = np.lib.utils._median_nancheck(asorted, s, axis, out)
else:
s = mid.mean(out=out)
@@ -758,6 +754,19 @@ def _median(a, axis=None, out=None, overwrite_input=False):
ind[axis] = np.minimum(h, asorted.shape[axis] - 1)
high = asorted[tuple(ind)]
+ def replace_masked(s):
+ # Replace masked entries with minimum_full_value unless it all values
+ # are masked. This is required as the sort order of values equal or
+ # larger than the fill value is undefined and a valid value placed
+ # elsewhere, e.g. [4, --, inf].
+ if np.ma.is_masked(s):
+ rep = (~np.all(asorted.mask, axis=axis)) & s.mask
+ s.data[rep] = np.ma.minimum_fill_value(asorted)
+ s.mask[rep] = False
+
+ replace_masked(low)
+ replace_masked(high)
+
# duplicate high if odd number of elements so mean does nothing
odd = counts % 2 == 1
np.copyto(low, high, where=odd)
@@ -776,12 +785,6 @@ def _median(a, axis=None, out=None, overwrite_input=False):
else:
s = np.ma.mean([low, high], axis=0, out=out)
- # if result is masked either the input contained enough minimum_fill_value
- # so that it would be the median or all values masked
- if np.ma.is_masked(s):
- rep = (~np.all(asorted.mask, axis=axis)) & s.mask
- s.data[rep] = np.ma.minimum_fill_value(asorted)
- s.mask[rep] = False
return s
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index b5be24b31..f72ddc5ea 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -4255,6 +4255,13 @@ class TestMaskedFields(TestCase):
a[0]['a'] = 2
assert_equal(a.mask, control)
+ def test_setitem_scalar(self):
+ # 8510
+ mask_0d = np.ma.masked_array(1, mask=True)
+ arr = np.ma.arange(3)
+ arr[0] = mask_0d
+ assert_array_equal(arr.mask, [True, False, False])
+
def test_element_len(self):
# check that len() works for mvoid (Github issue #576)
for rec in self.data['base']:
@@ -4425,6 +4432,28 @@ class TestOptionalArgs(TestCase):
assert_raises(ValueError, count, np.ma.array(1), axis=1)
+class TestMaskedConstant(TestCase):
+ def _do_add_test(self, add):
+ # sanity check
+ self.assertIs(add(np.ma.masked, 1), np.ma.masked)
+
+ # now try with a vector
+ vector = np.array([1, 2, 3])
+ result = add(np.ma.masked, vector)
+
+ # lots of things could go wrong here
+ assert_(result is not np.ma.masked)
+ assert_(not isinstance(result, np.ma.core.MaskedConstant))
+ assert_equal(result.shape, vector.shape)
+ assert_equal(np.ma.getmask(result), np.ones(vector.shape, dtype=bool))
+
+ def test_ufunc(self):
+ self._do_add_test(np.add)
+
+ def test_operator(self):
+ self._do_add_test(lambda a, b: a + b)
+
+
def test_masked_array():
a = np.ma.array([0, 1, 2, 3], mask=[0, 0, 1, 0])
assert_equal(np.argwhere(a), [[1], [3]])
@@ -4472,6 +4501,15 @@ def test_default_fill_value_complex():
# regression test for Python 3, where 'unicode' was not defined
assert_(default_fill_value(1 + 1j) == 1.e20 + 0.0j)
+
+def test_ufunc_with_output():
+ # check that giving an output argument always returns that output.
+ # Regression test for gh-8416.
+ x = array([1., 2., 3.], mask=[0, 0, 1])
+ y = np.add(x, 1., out=x)
+ assert_(y is x)
+
+
###############################################################################
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index fb16d92ce..fb68bd261 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -667,6 +667,15 @@ class TestMedian(TestCase):
r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
[np.inf, np.inf]]), axis=None)
assert_equal(r, np.inf)
+ # all masked
+ r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
+ [np.inf, np.inf]], mask=True),
+ axis=-1)
+ assert_equal(r.mask, True)
+ r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
+ [np.inf, np.inf]], mask=True),
+ axis=None)
+ assert_equal(r.mask, True)
def test_non_masked(self):
x = np.arange(9)
@@ -864,7 +873,6 @@ class TestMedian(TestCase):
def test_nan(self):
with suppress_warnings() as w:
w.record(RuntimeWarning)
- w.filter(DeprecationWarning, message=r"in 3\.x, __getslice__")
for mask in (False, np.zeros(6, dtype=np.bool)):
dm = np.ma.array([[1, np.nan, 3], [1, 2, 3]])
dm.mask = mask
@@ -914,7 +922,6 @@ class TestMedian(TestCase):
a[2] = np.nan
with suppress_warnings() as w:
w.record(RuntimeWarning)
- w.filter(DeprecationWarning, message=r"in 3\.x, __getslice__")
assert_array_equal(np.ma.median(a), np.nan)
assert_array_equal(np.ma.median(a, axis=0), np.nan)
assert_(w.log[0].category is RuntimeWarning)
@@ -929,7 +936,6 @@ class TestMedian(TestCase):
# no axis
with suppress_warnings() as w:
w.record(RuntimeWarning)
- w.filter(DeprecationWarning, message=r"in 3\.x, __getslice__")
warnings.filterwarnings('always', '', RuntimeWarning)
assert_array_equal(np.ma.median(a), np.nan)
assert_(np.isscalar(np.ma.median(a)))
@@ -992,6 +998,19 @@ class TestMedian(TestCase):
assert_equal(np.ma.median(a, axis=0), inf)
assert_equal(np.ma.median(a, axis=1), inf)
+ a = np.array([[inf, 7, -inf, -9],
+ [-10, np.nan, np.nan, 5],
+ [4, np.nan, np.nan, inf]],
+ dtype=np.float32)
+ a = np.ma.masked_array(a, mask=np.isnan(a))
+ if inf > 0:
+ assert_equal(np.ma.median(a, axis=0), [4., 7., -inf, 5.])
+ assert_equal(np.ma.median(a), 4.5)
+ else:
+ assert_equal(np.ma.median(a, axis=0), [-10., 7., -inf, -9.])
+ assert_equal(np.ma.median(a), -2.5)
+ assert_equal(np.ma.median(a, axis=1), [-1., -2.5, inf])
+
for i in range(0, 10):
for j in range(1, 10):
a = np.array([([np.nan] * i) + ([inf] * j)] * 2)
@@ -1006,7 +1025,6 @@ class TestMedian(TestCase):
a = np.ma.masked_array(np.array([], dtype=float))
with suppress_warnings() as w:
w.record(RuntimeWarning)
- w.filter(DeprecationWarning, message=r"in 3\.x, __getslice__")
assert_array_equal(np.ma.median(a), np.nan)
assert_(w.log[0].category is RuntimeWarning)
@@ -1015,7 +1033,6 @@ class TestMedian(TestCase):
# no axis
with suppress_warnings() as w:
w.record(RuntimeWarning)
- w.filter(DeprecationWarning, message=r"in 3\.x, __getslice__")
warnings.filterwarnings('always', '', RuntimeWarning)
assert_array_equal(np.ma.median(a), np.nan)
assert_(w.log[0].category is RuntimeWarning)
diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py
index 5d28b990f..3babb8fc2 100644
--- a/numpy/polynomial/chebyshev.py
+++ b/numpy/polynomial/chebyshev.py
@@ -1472,7 +1472,7 @@ def chebvander2d(x, y, deg):
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
points `(x, y)`. The pseudo-Vandermonde matrix is defined by
- .. math:: V[..., deg[1]*i + j] = T_i(x) * T_j(y),
+ .. math:: V[..., (deg[1] + 1)*i + j] = T_i(x) * T_j(y),
where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
`V` index the points `(x, y)` and the last index encodes the degrees of
@@ -1598,7 +1598,7 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None):
"""
Least squares fit of Chebyshev series to data.
- Return the coefficients of a Legendre series of degree `deg` that is the
+ Return the coefficients of a Chebyshev series of degree `deg` that is the
least squares fit to the data values `y` given at points `x`. If `y` is
1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
fits are done, one for each column of `y`, and the resulting
diff --git a/numpy/polynomial/hermite.py b/numpy/polynomial/hermite.py
index 00ca8702d..0ebae2027 100644
--- a/numpy/polynomial/hermite.py
+++ b/numpy/polynomial/hermite.py
@@ -1243,7 +1243,7 @@ def hermvander2d(x, y, deg):
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
points `(x, y)`. The pseudo-Vandermonde matrix is defined by
- .. math:: V[..., deg[1]*i + j] = H_i(x) * H_j(y),
+ .. math:: V[..., (deg[1] + 1)*i + j] = H_i(x) * H_j(y),
where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
`V` index the points `(x, y)` and the last index encodes the degrees of
diff --git a/numpy/polynomial/hermite_e.py b/numpy/polynomial/hermite_e.py
index 49888ee09..a09b66670 100644
--- a/numpy/polynomial/hermite_e.py
+++ b/numpy/polynomial/hermite_e.py
@@ -1240,7 +1240,7 @@ def hermevander2d(x, y, deg):
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
points `(x, y)`. The pseudo-Vandermonde matrix is defined by
- .. math:: V[..., deg[1]*i + j] = He_i(x) * He_j(y),
+ .. math:: V[..., (deg[1] + 1)*i + j] = He_i(x) * He_j(y),
where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
`V` index the points `(x, y)` and the last index encodes the degrees of
diff --git a/numpy/polynomial/laguerre.py b/numpy/polynomial/laguerre.py
index 49b0a9247..dfa997254 100644
--- a/numpy/polynomial/laguerre.py
+++ b/numpy/polynomial/laguerre.py
@@ -1242,7 +1242,7 @@ def lagvander2d(x, y, deg):
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
points `(x, y)`. The pseudo-Vandermonde matrix is defined by
- .. math:: V[..., deg[1]*i + j] = L_i(x) * L_j(y),
+ .. math:: V[..., (deg[1] + 1)*i + j] = L_i(x) * L_j(y),
where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
`V` index the points `(x, y)` and the last index encodes the degrees of
diff --git a/numpy/polynomial/legendre.py b/numpy/polynomial/legendre.py
index b54fd2982..fdaa56e0c 100644
--- a/numpy/polynomial/legendre.py
+++ b/numpy/polynomial/legendre.py
@@ -1273,7 +1273,7 @@ def legvander2d(x, y, deg):
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
points `(x, y)`. The pseudo-Vandermonde matrix is defined by
- .. math:: V[..., deg[1]*i + j] = L_i(x) * L_j(y),
+ .. math:: V[..., (deg[1] + 1)*i + j] = L_i(x) * L_j(y),
where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
`V` index the points `(x, y)` and the last index encodes the degrees of
diff --git a/numpy/polynomial/polynomial.py b/numpy/polynomial/polynomial.py
index eae2f8692..19b085eaf 100644
--- a/numpy/polynomial/polynomial.py
+++ b/numpy/polynomial/polynomial.py
@@ -1161,7 +1161,7 @@ def polyvander2d(x, y, deg):
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
points `(x, y)`. The pseudo-Vandermonde matrix is defined by
- .. math:: V[..., deg[1]*i + j] = x^i * y^j,
+ .. math:: V[..., (deg[1] + 1)*i + j] = x^i * y^j,
where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
`V` index the points `(x, y)` and the last index encodes the powers of
diff --git a/numpy/random/mtrand/mtrand.pyx b/numpy/random/mtrand/mtrand.pyx
index 65c19540e..bf3a385a9 100644
--- a/numpy/random/mtrand/mtrand.pyx
+++ b/numpy/random/mtrand/mtrand.pyx
@@ -4355,9 +4355,10 @@ cdef class RandomState:
self.lock)
# Multivariate distributions:
- def multivariate_normal(self, mean, cov, size=None):
+ def multivariate_normal(self, mean, cov, size=None, check_valid='warn',
+ tol=1e-8):
"""
- multivariate_normal(mean, cov[, size])
+ multivariate_normal(mean, cov[, size, check_valid, tol])
Draw random samples from a multivariate normal distribution.
@@ -4380,6 +4381,10 @@ cdef class RandomState:
generated, and packed in an `m`-by-`n`-by-`k` arrangement. Because
each sample is `N`-dimensional, the output shape is ``(m,n,k,N)``.
If no shape is specified, a single (`N`-D) sample is returned.
+ check_valid : { 'warn', 'raise', 'ignore' }, optional
+ Behavior when the covariance matrix is not positive semidefinite.
+ tol : float, optional
+ Tolerance when checking the singular values in covariance matrix.
Returns
-------
@@ -4464,11 +4469,11 @@ cdef class RandomState:
shape = size
if len(mean.shape) != 1:
- raise ValueError("mean must be 1 dimensional")
+ raise ValueError("mean must be 1 dimensional")
if (len(cov.shape) != 2) or (cov.shape[0] != cov.shape[1]):
- raise ValueError("cov must be 2 dimensional and square")
+ raise ValueError("cov must be 2 dimensional and square")
if mean.shape[0] != cov.shape[0]:
- raise ValueError("mean and cov must have same length")
+ raise ValueError("mean and cov must have same length")
# Compute shape of output and create a matrix of independent
# standard normally distributed random numbers. The matrix has rows
@@ -4491,12 +4496,20 @@ cdef class RandomState:
# not zero. We continue to use the SVD rather than Cholesky in
# order to preserve current outputs. Note that symmetry has not
# been checked.
+
(u, s, v) = svd(cov)
- neg = (np.sum(u.T * v, axis=1) < 0) & (s > 0)
- if np.any(neg):
- s[neg] = 0.
- warnings.warn("covariance is not positive-semidefinite.",
- RuntimeWarning)
+
+ if check_valid != 'ignore':
+ if check_valid != 'warn' and check_valid != 'raise':
+ raise ValueError("check_valid must equal 'warn', 'raise', or 'ignore'")
+
+ psd = np.allclose(np.dot(v.T * s, v), cov, rtol=tol, atol=tol)
+ if not psd:
+ if check_valid == 'warn':
+ warnings.warn("covariance is not positive-semidefinite.",
+ RuntimeWarning)
+ else:
+ raise ValueError("covariance is not positive-semidefinite.")
x = np.dot(x, np.sqrt(s)[:, None] * v)
x += mean
diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py
index 47301a770..dc7d18933 100644
--- a/numpy/random/tests/test_random.py
+++ b/numpy/random/tests/test_random.py
@@ -1,10 +1,11 @@
from __future__ import division, absolute_import, print_function
+import warnings
import numpy as np
from numpy.testing import (
TestCase, run_module_suite, assert_, assert_raises, assert_equal,
- assert_warns, assert_array_equal, assert_array_almost_equal,
- suppress_warnings)
+ assert_warns, assert_no_warnings, assert_array_equal,
+ assert_array_almost_equal, suppress_warnings)
from numpy import random
from numpy.compat import asbytes
import sys
@@ -579,10 +580,6 @@ class TestRandomDist(TestCase):
[-0.21682183359214885, 2.63373365386060332]])
assert_array_almost_equal(actual, desired, decimal=15)
- def test_laplace_0(self):
- assert_(np.random.laplace(scale=0) in [0, 1])
- assert_raises(ValueError, np.random.laplace, scale=-0.)
-
def test_lognormal(self):
np.random.seed(self.seed)
actual = np.random.lognormal(mean=.123456789, sigma=2.0, size=(3, 2))
@@ -617,28 +614,37 @@ class TestRandomDist(TestCase):
def test_multivariate_normal(self):
np.random.seed(self.seed)
mean = (.123456789, 10)
- # Hmm... not even symmetric.
- cov = [[1, 0], [1, 0]]
+ cov = [[1, 0], [0, 1]]
size = (3, 2)
actual = np.random.multivariate_normal(mean, cov, size)
- desired = np.array([[[-1.47027513018564449, 10.],
- [-1.65915081534845532, 10.]],
- [[-2.29186329304599745, 10.],
- [-1.77505606019580053, 10.]],
- [[-0.54970369430044119, 10.],
- [0.29768848031692957, 10.]]])
+ desired = np.array([[[1.463620246718631, 11.73759122771936 ],
+ [1.622445133300628, 9.771356667546383]],
+ [[2.154490787682787, 12.170324946056553],
+ [1.719909438201865, 9.230548443648306]],
+ [[0.689515026297799, 9.880729819607714],
+ [-0.023054015651998, 9.201096623542879]]])
+
assert_array_almost_equal(actual, desired, decimal=15)
# Check for default size, was raising deprecation warning
actual = np.random.multivariate_normal(mean, cov)
- desired = np.array([-0.79441224511977482, 10.])
+ desired = np.array([0.895289569463708, 9.17180864067987])
assert_array_almost_equal(actual, desired, decimal=15)
- # Check that non positive-semidefinite covariance raises warning
+ # Check that non positive-semidefinite covariance warns with
+ # RuntimeWarning
mean = [0, 0]
- cov = [[1, 1 + 1e-10], [1 + 1e-10, 1]]
+ cov = [[1, 2], [2, 1]]
assert_warns(RuntimeWarning, np.random.multivariate_normal, mean, cov)
+ # and that it doesn't warn with RuntimeWarning check_valid='ignore'
+ assert_no_warnings(np.random.multivariate_normal, mean, cov,
+ check_valid='ignore')
+
+ # and that it raises with RuntimeWarning check_valid='raises'
+ assert_raises(ValueError, np.random.multivariate_normal, mean, cov,
+ check_valid='raise')
+
def test_negative_binomial(self):
np.random.seed(self.seed)
actual = np.random.negative_binomial(n=100, p=.12345, size=(3, 2))
@@ -813,7 +819,9 @@ class TestRandomDist(TestCase):
assert_raises(OverflowError, func, [0], [np.inf])
# (fmax / 1e17) - fmin is within range, so this should not throw
- np.random.uniform(low=fmin, high=fmax / 1e17)
+ # account for i386 extended precision DBL_MAX / 1e17 + DBL_MAX >
+ # DBL_MAX by increasing fmin a bit
+ np.random.uniform(low=np.nextafter(fmin, 1), high=fmax / 1e17)
def test_vonmises(self):
np.random.seed(self.seed)
diff --git a/numpy/testing/nosetester.py b/numpy/testing/nosetester.py
index 3d9616ed8..da5d112f5 100644
--- a/numpy/testing/nosetester.py
+++ b/numpy/testing/nosetester.py
@@ -420,8 +420,6 @@ class NoseTester(object):
sup.filter(DeprecationWarning,
r"sys\.exc_clear\(\) not supported in 3\.x",
module=threading)
- sup.filter(DeprecationWarning, message=r"in 3\.x, __setslice__")
- sup.filter(DeprecationWarning, message=r"in 3\.x, __getslice__")
sup.filter(DeprecationWarning, message=r"buffer\(\) not supported in 3\.x")
sup.filter(DeprecationWarning, message=r"CObject type is not supported in 3\.x")
sup.filter(DeprecationWarning, message=r"comparing unequal types not supported in 3\.x")
diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py
index 474a7edd5..804f22b7f 100644
--- a/numpy/testing/tests/test_utils.py
+++ b/numpy/testing/tests/test_utils.py
@@ -291,14 +291,46 @@ class TestArrayAlmostEqual(_GenericTest, unittest.TestCase):
a[0, 0] = np.inf
self.assertRaises(AssertionError,
lambda: self._assert_func(a, b))
+ b[0, 0] = -np.inf
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(a, b))
def test_subclass(self):
a = np.array([[1., 2.], [3., 4.]])
b = np.ma.masked_array([[1., 2.], [0., 4.]],
[[False, False], [True, False]])
- assert_array_almost_equal(a, b)
- assert_array_almost_equal(b, a)
- assert_array_almost_equal(b, b)
+ self._assert_func(a, b)
+ self._assert_func(b, a)
+ self._assert_func(b, b)
+
+ def test_matrix(self):
+ # Matrix slicing keeps things 2-D, while array does not necessarily.
+ # See gh-8452.
+ m1 = np.matrix([[1., 2.]])
+ m2 = np.matrix([[1., np.nan]])
+ m3 = np.matrix([[1., -np.inf]])
+ m4 = np.matrix([[np.nan, np.inf]])
+ m5 = np.matrix([[1., 2.], [np.nan, np.inf]])
+ for m in m1, m2, m3, m4, m5:
+ self._assert_func(m, m)
+ a = np.array(m)
+ self._assert_func(a, m)
+ self._assert_func(m, a)
+
+ def test_subclass_that_cannot_be_bool(self):
+ # While we cannot guarantee testing functions will always work for
+ # subclasses, the tests should ideally rely only on subclasses having
+ # comparison operators, not on them being able to store booleans
+ # (which, e.g., astropy Quantity cannot usefully do). See gh-8452.
+ class MyArray(np.ndarray):
+ def __lt__(self, other):
+ return super(MyArray, self).__lt__(other).view(np.ndarray)
+
+ def all(self, *args, **kwargs):
+ raise NotImplementedError
+
+ a = np.array([1., 2.]).view(MyArray)
+ self._assert_func(a, a)
class TestAlmostEqual(_GenericTest, unittest.TestCase):
@@ -337,6 +369,8 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
self._assert_func(-np.inf, -np.inf)
self.assertRaises(AssertionError,
lambda: self._assert_func(np.inf, 1))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(-np.inf, np.inf))
def test_simple_item(self):
self._test_not_equal(1, 2)
@@ -382,6 +416,35 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
# remove anything that's not the array string
self.assertEqual(str(e).split('%)\n ')[1], b)
+ def test_matrix(self):
+ # Matrix slicing keeps things 2-D, while array does not necessarily.
+ # See gh-8452.
+ m1 = np.matrix([[1., 2.]])
+ m2 = np.matrix([[1., np.nan]])
+ m3 = np.matrix([[1., -np.inf]])
+ m4 = np.matrix([[np.nan, np.inf]])
+ m5 = np.matrix([[1., 2.], [np.nan, np.inf]])
+ for m in m1, m2, m3, m4, m5:
+ self._assert_func(m, m)
+ a = np.array(m)
+ self._assert_func(a, m)
+ self._assert_func(m, a)
+
+ def test_subclass_that_cannot_be_bool(self):
+ # While we cannot guarantee testing functions will always work for
+ # subclasses, the tests should ideally rely only on subclasses having
+ # comparison operators, not on them being able to store booleans
+ # (which, e.g., astropy Quantity cannot usefully do). See gh-8452.
+ class MyArray(np.ndarray):
+ def __lt__(self, other):
+ return super(MyArray, self).__lt__(other).view(np.ndarray)
+
+ def all(self, *args, **kwargs):
+ raise NotImplementedError
+
+ a = np.array([1., 2.]).view(MyArray)
+ self._assert_func(a, a)
+
class TestApproxEqual(unittest.TestCase):
@@ -432,6 +495,146 @@ class TestApproxEqual(unittest.TestCase):
lambda: self._assert_func(ainf, anan))
+class TestArrayAssertLess(unittest.TestCase):
+
+ def setUp(self):
+ self._assert_func = assert_array_less
+
+ def test_simple_arrays(self):
+ x = np.array([1.1, 2.2])
+ y = np.array([1.2, 2.3])
+
+ self._assert_func(x, y)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ y = np.array([1.0, 2.3])
+
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, y))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ def test_rank2(self):
+ x = np.array([[1.1, 2.2], [3.3, 4.4]])
+ y = np.array([[1.2, 2.3], [3.4, 4.5]])
+
+ self._assert_func(x, y)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ y = np.array([[1.0, 2.3], [3.4, 4.5]])
+
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, y))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ def test_rank3(self):
+ x = np.ones(shape=(2, 2, 2))
+ y = np.ones(shape=(2, 2, 2))+1
+
+ self._assert_func(x, y)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ y[0, 0, 0] = 0
+
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, y))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ def test_simple_items(self):
+ x = 1.1
+ y = 2.2
+
+ self._assert_func(x, y)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ y = np.array([2.2, 3.3])
+
+ self._assert_func(x, y)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(y, x))
+
+ y = np.array([1.0, 3.3])
+
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, y))
+
+ def test_nan_noncompare(self):
+ anan = np.array(np.nan)
+ aone = np.array(1)
+ ainf = np.array(np.inf)
+ self._assert_func(anan, anan)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(aone, anan))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(anan, aone))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(anan, ainf))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(ainf, anan))
+
+ def test_nan_noncompare_array(self):
+ x = np.array([1.1, 2.2, 3.3])
+ anan = np.array(np.nan)
+
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, anan))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(anan, x))
+
+ x = np.array([1.1, 2.2, np.nan])
+
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, anan))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(anan, x))
+
+ y = np.array([1.0, 2.0, np.nan])
+
+ self._assert_func(y, x)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, y))
+
+ def test_inf_compare(self):
+ aone = np.array(1)
+ ainf = np.array(np.inf)
+
+ self._assert_func(aone, ainf)
+ self._assert_func(-ainf, aone)
+ self._assert_func(-ainf, ainf)
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(ainf, aone))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(aone, -ainf))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(ainf, ainf))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(ainf, -ainf))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(-ainf, -ainf))
+
+ def test_inf_compare_array(self):
+ x = np.array([1.1, 2.2, np.inf])
+ ainf = np.array(np.inf)
+
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, ainf))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(ainf, x))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(x, -ainf))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(-x, -ainf))
+ self.assertRaises(AssertionError,
+ lambda: self._assert_func(-ainf, -x))
+ self._assert_func(-ainf, x)
+
+
class TestRaises(unittest.TestCase):
def setUp(self):
diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py
index 859a0705b..b5a7e05c4 100644
--- a/numpy/testing/utils.py
+++ b/numpy/testing/utils.py
@@ -82,6 +82,7 @@ def assert_(val, msg=''):
For documentation on usage, refer to the Python documentation.
"""
+ __tracebackhide__ = True # Hide traceback for py.test
if not val:
try:
smsg = msg()
@@ -666,9 +667,10 @@ def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True):
def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
- header='', precision=6, equal_nan=True):
+ header='', precision=6, equal_nan=True,
+ equal_inf=True):
__tracebackhide__ = True # Hide traceback for py.test
- from numpy.core import array, isnan, isinf, any, all, inf
+ from numpy.core import array, isnan, isinf, any, inf
x = array(x, copy=False, subok=True)
y = array(y, copy=False, subok=True)
@@ -720,40 +722,41 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
y.shape),
verbose=verbose, header=header,
names=('x', 'y'), precision=precision)
- if not cond:
- raise AssertionError(msg)
+ raise AssertionError(msg)
if isnumber(x) and isnumber(y):
+ has_nan = has_inf = False
if equal_nan:
x_isnan, y_isnan = isnan(x), isnan(y)
# Validate that NaNs are in the same place
- if any(x_isnan) or any(y_isnan):
+ has_nan = any(x_isnan) or any(y_isnan)
+ if has_nan:
chk_same_position(x_isnan, y_isnan, hasval='nan')
- x_isinf, y_isinf = isinf(x), isinf(y)
-
- # Validate that infinite values are in the same place
- if any(x_isinf) or any(y_isinf):
- # Check +inf and -inf separately, since they are different
- chk_same_position(x == +inf, y == +inf, hasval='+inf')
- chk_same_position(x == -inf, y == -inf, hasval='-inf')
-
- # Combine all the special values
- x_id, y_id = x_isinf, y_isinf
- if equal_nan:
- x_id |= x_isnan
- y_id |= y_isnan
+ if equal_inf:
+ x_isinf, y_isinf = isinf(x), isinf(y)
+ # Validate that infinite values are in the same place
+ has_inf = any(x_isinf) or any(y_isinf)
+ if has_inf:
+ # Check +inf and -inf separately, since they are different
+ chk_same_position(x == +inf, y == +inf, hasval='+inf')
+ chk_same_position(x == -inf, y == -inf, hasval='-inf')
+
+ if has_nan and has_inf:
+ x = x[~(x_isnan | x_isinf)]
+ y = y[~(y_isnan | y_isinf)]
+ elif has_nan:
+ x = x[~x_isnan]
+ y = y[~y_isnan]
+ elif has_inf:
+ x = x[~x_isinf]
+ y = y[~y_isinf]
# Only do the comparison if actual values are left
- if all(x_id):
+ if x.size == 0:
return
- if any(x_id):
- val = safe_comparison(x[~x_id], y[~y_id])
- else:
- val = safe_comparison(x, y)
- else:
- val = safe_comparison(x, y)
+ val = safe_comparison(x, y)
if isinstance(val, bool):
cond = val
@@ -844,6 +847,7 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
... rtol=1e-10, atol=0)
"""
+ __tracebackhide__ = True # Hide traceback for py.test
assert_array_compare(operator.__eq__, x, y, err_msg=err_msg,
verbose=verbose, header='Arrays are not equal')
@@ -930,7 +934,7 @@ def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True):
if npany(gisinf(x)) or npany( gisinf(y)):
xinfid = gisinf(x)
yinfid = gisinf(y)
- if not xinfid == yinfid:
+ if not (xinfid == yinfid).all():
return False
# if one item, x and y is +- inf
if x.size == y.size == 1:
@@ -1025,7 +1029,8 @@ def assert_array_less(x, y, err_msg='', verbose=True):
__tracebackhide__ = True # Hide traceback for py.test
assert_array_compare(operator.__lt__, x, y, err_msg=err_msg,
verbose=verbose,
- header='Arrays are not less-ordered')
+ header='Arrays are not less-ordered',
+ equal_inf=False)
def runstring(astr, dict):
diff --git a/pavement.py b/pavement.py
index 5fc936788..7ab43bb04 100644
--- a/pavement.py
+++ b/pavement.py
@@ -582,14 +582,14 @@ def compute_sha256(idirs):
return checksums
-def write_release_task(options, filename='NOTES.txt'):
+def write_release_task(options, filename='README'):
idirs = options.installers.installersdir
source = paver.path.path(RELEASE_NOTES)
target = paver.path.path(filename)
if target.exists():
target.remove()
- tmp_target = paver.path.path(filename + '.tmp')
+ tmp_target = paver.path.path(filename + '.md')
source.copy(tmp_target)
with open(str(tmp_target), 'a') as ftarget:
@@ -598,16 +598,16 @@ Checksums
=========
MD5
-~~~
+---
""")
- ftarget.writelines(['%s\n' % c for c in compute_md5(idirs)])
+ ftarget.writelines([' %s\n' % c for c in compute_md5(idirs)])
ftarget.writelines("""
SHA256
-~~~~~~
+------
""")
- ftarget.writelines(['%s\n' % c for c in compute_sha256(idirs)])
+ ftarget.writelines([' %s\n' % c for c in compute_sha256(idirs)])
# Sign release
cmd = ['gpg', '--clearsign', '--armor']
@@ -616,7 +616,14 @@ SHA256
cmd += ['--output', str(target), str(tmp_target)]
subprocess.check_call(cmd)
print("signed %s" % (target,))
- tmp_target.remove()
+
+ # Change PR links for github posting, don't sign this
+ # as the signing isn't markdown compatible.
+ with open(str(tmp_target), 'r') as ftarget:
+ mdtext = ftarget.read()
+ mdtext = re.sub(r'^\* `(\#[0-9]*).*?`__', r'* \1', mdtext, flags=re.M)
+ with open(str(tmp_target), 'w') as ftarget:
+ ftarget.write(mdtext)
def write_log_task(options, filename='Changelog'):
diff --git a/tools/announce.py b/tools/announce.py
index 5b40cc3b0..05ea8cb36 100755
--- a/tools/announce.py
+++ b/tools/announce.py
@@ -110,25 +110,26 @@ def main(token, revision_range):
# document authors
authors = get_authors(revision_range)
- heading = u"Contributors to {0}".format(cur_release)
+ heading = u"Contributors"
print()
print(heading)
print(u"="*len(heading))
print(author_msg % len(authors))
for s in authors:
- print(u'- ' + s)
+ print(u'* ' + s)
# document pull requests
pull_requests = get_pull_requests(github_repo, revision_range)
- heading = u"Pull requests merged for {0}".format(cur_release)
+ heading = u"Pull requests merged"
+ pull_msg = u"* `#{0} <{1}>`__: {2}"
+
print()
print(heading)
print(u"="*len(heading))
print(pull_request_msg % len(pull_requests))
for pull in pull_requests:
- pull_msg = u"- `#{0} <{1}>`__: {2}"
title = re.sub(u"\\s+", u" ", pull.title.strip())
if len(title) > 60:
remainder = re.sub(u"\\s.*$", u"...", title[60:])
diff --git a/tools/travis-test.sh b/tools/travis-test.sh
index 91c871560..e050b4ccb 100755
--- a/tools/travis-test.sh
+++ b/tools/travis-test.sh
@@ -8,7 +8,10 @@ export NPY_NUM_BUILD_JOBS=2
# setup env
if [ -r /usr/lib/libeatmydata/libeatmydata.so ]; then
# much faster package installation
- export LD_PRELOAD=/usr/lib/libeatmydata/libeatmydata.so
+ export LD_PRELOAD='/usr/lib/libeatmydata/libeatmydata.so'
+elif [ -r /usr/lib/*/libeatmydata.so ]; then
+ # much faster package installation
+ export LD_PRELOAD='/usr/$LIB/libeatmydata.so'
fi
source builds/venv/bin/activate
@@ -47,9 +50,9 @@ setup_base()
else
sysflags="$($PYTHON -c "from distutils import sysconfig; \
print (sysconfig.get_config_var('CFLAGS'))")"
- CFLAGS="$sysflags $werrors -Wlogical-op" $PIP install . 2>&1 | tee log
+ CFLAGS="$sysflags $werrors -Wlogical-op" $PIP install -v . 2>&1 | tee log
grep -v "_configtest" log \
- | grep -vE "ld returned 1|no previously-included files matching" \
+ | grep -vE "ld returned 1|no previously-included files matching|manifest_maker: standard file '-c'" \
| grep -E "warning\>" \
| tee warnings
# Check for an acceptable number of warnings. Some warnings are out of
@@ -95,15 +98,16 @@ setup_chroot()
$DIST-security main restricted universe multiverse \
| sudo tee -a $DIR/etc/apt/sources.list
- # install needed packages
sudo chroot $DIR bash -c "apt-get update"
- sudo chroot $DIR bash -c "apt-get install -qq -y --force-yes \
- eatmydata libatlas-dev libatlas-base-dev gfortran \
- python-dev python-nose python-pip cython"
-
# faster operation with preloaded eatmydata
- echo /usr/lib/libeatmydata/libeatmydata.so | \
+ sudo chroot $DIR bash -c "apt-get install -qq -y --force-yes eatmydata"
+ echo '/usr/$LIB/libeatmydata.so' | \
sudo tee -a $DIR/etc/ld.so.preload
+
+ # install needed packages
+ sudo chroot $DIR bash -c "apt-get install -qq -y --force-yes \
+ libatlas-dev libatlas-base-dev gfortran \
+ python-dev python-nose python-pip cython"
}
run_test()