Imported Upstream version 1.17.1 upstream/1.17.1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 00:49:15 +0000 (09:49 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 00:49:15 +0000 (09:49 +0900)
49 files changed:
.circleci/config.yml
.mailmap
.travis.yml
doc/Makefile
doc/changelog/1.17.1-changelog.rst [new file with mode: 0644]
doc/release/1.17.1-notes.rst [new file with mode: 0644]
doc/source/release.rst
numpy/core/_internal.py
numpy/core/arrayprint.py
numpy/core/include/numpy/npy_math.h
numpy/core/records.py
numpy/core/src/multiarray/alloc.c
numpy/core/src/multiarray/compiled_base.c
numpy/core/src/multiarray/datetime.c
numpy/core/src/multiarray/descriptor.c
numpy/core/src/multiarray/item_selection.c
numpy/core/src/multiarray/mapping.c
numpy/core/src/umath/simd.inc.src
numpy/core/tests/test_deprecations.py
numpy/core/tests/test_indexing.py
numpy/core/tests/test_records.py
numpy/core/tests/test_regression.py
numpy/core/tests/test_umath.py
numpy/ctypeslib.py
numpy/f2py/rules.py [changed mode: 0644->0755]
numpy/f2py/src/fortranobject.c
numpy/fft/tests/test_pocketfft.py
numpy/lib/_iotools.py
numpy/lib/npyio.py
numpy/lib/recfunctions.py
numpy/lib/tests/test_io.py
numpy/lib/tests/test_recfunctions.py
numpy/linalg/linalg.py
numpy/ma/core.py
numpy/ma/mrecords.py
numpy/ma/tests/test_core.py
numpy/random/__init__.py
numpy/random/_pickle.py
numpy/random/bit_generator.pxd
numpy/random/bit_generator.pyx
numpy/random/common.pyx
numpy/random/generator.pyx
numpy/random/mtrand.pyx
numpy/random/setup.py
numpy/random/tests/test_generator_mt19937.py
numpy/random/tests/test_randomstate.py
pavement.py
setup.py
tools/travis-before-install.sh

index ff26afeb8a898d7d4ecbed9adea21850ea561124..6b4ab812ff9deba909f7ed9aef8340990f75cb47 100644 (file)
@@ -19,6 +19,7 @@ jobs:
           name: install dependencies
           command: |
             python3 -m venv venv
+            ln -s $(which python3) venv/bin/python3.6
             . venv/bin/activate
             pip install cython sphinx==1.8.5 matplotlib ipython
             sudo apt-get update
index d3659421268ef8561e15b262cbcdf6a0791d090b..9d7aaa3c43dc15b0ececaaeb26c582f6bef66985 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -22,6 +22,7 @@ Alex Thomas <alexthomas93@users.noreply.github.com> alexthomas93 <alexthomas93@u
 Alexander Belopolsky <abalkin@enlnt.com> Alexander Belopolsky <a@enlnt.com>
 Alexander Belopolsky <abalkin@enlnt.com> Alexander Belopolsky <a@enlnt.com>
 Alexander Belopolsky <abalkin@enlnt.com> sasha <sasha@localhost>
+Alexander Jung <kontakt@ajung.name> aleju <kontakt@ajung.name>
 Alexander Shadchin <alexandr.shadchin@gmail.com> Alexandr Shadchin <alexandr.shadchin@gmail.com>
 Alexander Shadchin <alexandr.shadchin@gmail.com> shadchin <alexandr.shadchin@gmail.com>
 Allan Haldane <allan.haldane@gmail.com> ahaldane <ealloc@gmail.com>
@@ -142,6 +143,7 @@ Kiko Correoso <kachine@protonmail.com> kikocorreoso <kikocorreoso@gmail.com>
 Kiko Correoso <kachine@protonmail.com> kikocorreoso <kikocorreoso@users.noreply.github.com>
 Konrad Kapp <k_kapp@yahoo.com> k_kapp@yahoo.com <k_kapp@yahoo.com>
 Kriti Singh <kritisingh1.ks@gmail.com> kritisingh1 <kritisingh1.ks@gmail.com>
+Kmol Yuan <pyslvs@gmail.com> Yuan <pyslvs@gmail.com>
 Lars Buitinck <larsmans@gmail.com> Lars Buitinck <l.buitinck@esciencecenter.nl>
 Lars Buitinck <larsmans@gmail.com> Lars Buitinck <L.J.Buitinck@uva.nl>
 Lars GrĂ¼ter <lagru@mailbox.org> Lars G <lagru@mailbox.org>
index b54e871cd9a46311b067d3fbcf034b079e40a3de..ebfa713b2e3b8b17acf307c8de8d73644d1a6964 100644 (file)
@@ -10,7 +10,6 @@ addons:
   apt:
     packages: &common_packages
       - gfortran
-      - libatlas-dev
       - libatlas-base-dev
       # Speedup builds, particularly when USE_CHROOT=1
       - eatmydata
@@ -33,6 +32,7 @@ env:
 python:
   - 3.5
   - 3.6
+  - 3.8-dev
 matrix:
   include:
     - python: 3.7
index 842d2ad13c81729d31a2d0e2099362915d18295a..00393abc6b9e2c086a83cd9f271e5526a5bcda88 100644 (file)
 PYVER:=$(shell python3 -c 'from sys import version_info as v; print("{0}.{1}".format(v[0], v[1]))')
 PYTHON = python$(PYVER)
 
-NUMPYVER:=$(shell python3 -c "import numpy; print(numpy.version.git_revision[:10])")
-GITVER ?= $(shell cd ..; python3 -c "from setup import git_version; \
-                               print(git_version()[:10])")
-
 # You can set these variables from the command line.
 SPHINXOPTS    ?=
 SPHINXBUILD   ?= LANG=C sphinx-build
@@ -28,7 +24,7 @@ ALLSPHINXOPTS   = -WT --keep-going -d build/doctrees $(PAPEROPT_$(PAPER)) \
   $(SPHINXOPTS) source
 
 .PHONY: help clean html web pickle htmlhelp latex changes linkcheck \
-        dist dist-build gitwash-update version-check
+        dist dist-build gitwash-update version-check html-build latex-build
 
 #------------------------------------------------------------------------------
 
@@ -49,18 +45,6 @@ clean:
        -rm -rf build/* 
        find . -name generated -type d -prune -exec rm -rf "{}" ";"
 
-version-check:
-ifeq "$(GITVER)" "Unknown"
-       # @echo sdist build with unlabeled sources
-else ifneq ($(NUMPYVER),$(GITVER))
-       @echo installed numpy $(NUMPYVER) != current repo git version \'$(GITVER)\'
-       @echo use '"make dist"' or '"GITVER=$(NUMPYVER) make $(MAKECMDGOALS) ..."'
-       @exit 1
-else
-       # for testing
-       # @echo installed numpy $(NUMPYVER) matches git version $(GITVER); exit 1
-endif
-
 gitwash-update:
        rm -rf source/dev/gitwash
        install -d source/dev/gitwash
@@ -86,15 +70,34 @@ INSTALL_DIR = $(CURDIR)/build/inst-dist
 INSTALL_PPH = $(INSTALL_DIR)/lib/python$(PYVER)/site-packages:$(INSTALL_DIR)/local/lib/python$(PYVER)/site-packages:$(INSTALL_DIR)/lib/python$(PYVER)/dist-packages:$(INSTALL_DIR)/local/lib/python$(PYVER)/dist-packages
 UPLOAD_DIR=/srv/docs_scipy_org/doc/numpy-$(RELEASE)
 
-DIST_VARS=SPHINXBUILD="LANG=C PYTHONPATH=$(INSTALL_PPH) python$(PYVER) `which sphinx-build`" PYTHON="PYTHONPATH=$(INSTALL_PPH) python$(PYVER)" SPHINXOPTS="$(SPHINXOPTS)"
+DIST_VARS=SPHINXBUILD="LANG=C PYTHONPATH=$(INSTALL_PPH) python$(PYVER) `which sphinx-build`" PYTHON="PYTHONPATH=$(INSTALL_PPH) python$(PYVER)" 
+
+NUMPYVER:=$(shell $(PYTHON) -c "import numpy; print(numpy.version.git_revision[:10])" 2>/dev/null)
+GITVER ?= $(shell cd ..; $(PYTHON) -c "from setup import git_version; \
+                               print(git_version()[:10])")
+
+version-check:
+ifeq "$(GITVER)" "Unknown"
+       # @echo sdist build with unlabeled sources
+else ifeq ("", "$(NUMPYVER)")
+       @echo numpy not found, cannot build documentation without successful \"import numpy\"
+       @exit 1
+else ifneq ($(NUMPYVER),$(GITVER))
+       @echo installed numpy $(NUMPYVER) != current repo git version \'$(GITVER)\'
+       @echo use '"make dist"' or '"GITVER=$(NUMPYVER) make $(MAKECMDGOALS) ..."'
+       @exit 1
+else
+       # for testing
+       # @echo installed numpy $(NUMPYVER) matches git version $(GITVER); exit 1
+endif
+
 
 dist:
        make $(DIST_VARS) real-dist
 
-real-dist: dist-build html html-scipyorg
-       test -d build/latex || make latex
+real-dist: dist-build html-build html-scipyorg
+       test -d build/latex || make latex-build
        make -C build/latex all-pdf
-       -test -d build/htmlhelp || make htmlhelp-build
        -rm -rf build/dist
        cp -r build/html-scipyorg build/dist
        cd build/html && zip -9r ../dist/numpy-html.zip .
@@ -136,7 +139,8 @@ build/generate-stamp: $(wildcard source/reference/*.rst)
        mkdir -p build
        touch build/generate-stamp
 
-html: generate version-check
+html: version-check html-build
+html-build: generate
        mkdir -p build/html build/doctrees
        $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html $(FILES)
        $(PYTHON) postprocess.py html build/html/*.html
@@ -174,7 +178,8 @@ qthelp: generate version-check
        mkdir -p build/qthelp build/doctrees
        $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) build/qthelp $(FILES)
 
-latex: generate version-check
+latex: version-check latex-build
+latex-build: generate
        mkdir -p build/latex build/doctrees
        $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex $(FILES)
        $(PYTHON) postprocess.py tex build/latex/*.tex
diff --git a/doc/changelog/1.17.1-changelog.rst b/doc/changelog/1.17.1-changelog.rst
new file mode 100644 (file)
index 0000000..c7c8b6c
--- /dev/null
@@ -0,0 +1,55 @@
+
+Contributors
+============
+
+A total of 17 people contributed to this release.  People with a "+" by their
+names contributed a patch for the first time.
+
+* Alexander Jung +
+* Allan Haldane
+* Charles Harris
+* Eric Wieser
+* Giuseppe Cuccu +
+* Hiroyuki V. Yamazaki
+* JĂ©rĂ©mie du Boisberranger
+* Kmol Yuan +
+* Matti Picus
+* Max Bolingbroke +
+* Maxwell Aladago +
+* Oleksandr Pavlyk
+* Peter Andreas Entschev
+* Sergei Lebedev
+* Seth Troisi +
+* Vladimir Pershin +
+* Warren Weckesser
+
+Pull requests merged
+====================
+
+A total of 24 pull requests were merged for this release.
+
+* `#14156 <https://github.com/numpy/numpy/pull/14156>`__: TST: Allow fuss in testing strided/non-strided exp/log loops
+* `#14157 <https://github.com/numpy/numpy/pull/14157>`__: BUG: avx2_scalef_ps must be static
+* `#14158 <https://github.com/numpy/numpy/pull/14158>`__: BUG: Remove stray print that causes a SystemError on python 3.7.
+* `#14159 <https://github.com/numpy/numpy/pull/14159>`__: BUG: Fix DeprecationWarning in python 3.8.
+* `#14160 <https://github.com/numpy/numpy/pull/14160>`__: BLD: Add missing gcd/lcm definitions to npy_math.h
+* `#14161 <https://github.com/numpy/numpy/pull/14161>`__: DOC, BUILD: cleanups and fix (again) 'build dist'
+* `#14166 <https://github.com/numpy/numpy/pull/14166>`__: TST: Add 3.8-dev to travisCI testing.
+* `#14194 <https://github.com/numpy/numpy/pull/14194>`__: BUG: Remove the broken clip wrapper (Backport)
+* `#14198 <https://github.com/numpy/numpy/pull/14198>`__: DOC: Fix hermitian argument docs in svd.
+* `#14199 <https://github.com/numpy/numpy/pull/14199>`__: MAINT: Workaround for Intel compiler bug leading to failing test
+* `#14200 <https://github.com/numpy/numpy/pull/14200>`__: TST: Clean up of test_pocketfft.py
+* `#14201 <https://github.com/numpy/numpy/pull/14201>`__: BUG: Make advanced indexing result on read-only subclass writeable...
+* `#14236 <https://github.com/numpy/numpy/pull/14236>`__: BUG: Fixed default BitGenerator name
+* `#14237 <https://github.com/numpy/numpy/pull/14237>`__: ENH: add c-imported modules for freeze analysis in np.random
+* `#14296 <https://github.com/numpy/numpy/pull/14296>`__: TST: Pin pytest version to 5.0.1
+* `#14301 <https://github.com/numpy/numpy/pull/14301>`__: BUG: Fix leak in the f2py-generated module init and `PyMem_Del`...
+* `#14302 <https://github.com/numpy/numpy/pull/14302>`__: BUG: Fix formatting error in exception message
+* `#14307 <https://github.com/numpy/numpy/pull/14307>`__: MAINT: random: Match type of SeedSequence.pool_size to DEFAULT_POOL_SIZE.
+* `#14308 <https://github.com/numpy/numpy/pull/14308>`__: BUG: Fix numpy.random bug in platform detection
+* `#14309 <https://github.com/numpy/numpy/pull/14309>`__: ENH: Enable huge pages in all Linux builds
+* `#14330 <https://github.com/numpy/numpy/pull/14330>`__: BUG: Fix segfault in `random.permutation(x)` when x is a string.
+* `#14338 <https://github.com/numpy/numpy/pull/14338>`__: BUG: don't fail when lexsorting some empty arrays (#14228)
+* `#14339 <https://github.com/numpy/numpy/pull/14339>`__: BUG: Fix misuse of .names and .fields in various places (backport...
+* `#14345 <https://github.com/numpy/numpy/pull/14345>`__: BUG: fix behavior of structured_to_unstructured on non-trivial...
+* `#14350 <https://github.com/numpy/numpy/pull/14350>`__: REL: Prepare 1.17.1 release
diff --git a/doc/release/1.17.1-notes.rst b/doc/release/1.17.1-notes.rst
new file mode 100644 (file)
index 0000000..bd837ee
--- /dev/null
@@ -0,0 +1,73 @@
+.. currentmodule:: numpy
+
+==========================
+NumPy 1.17.1 Release Notes
+==========================
+
+This release contains a number of fixes for bugs reported against NumPy 1.17.0
+along with a few documentation and build improvements.  The Python versions
+supported are 3.5-3.7, note that Python 2.7 has been dropped.  Python 3.8b3
+should work with the released source packages, but there are no future
+guarantees.
+
+Downstream developers should use Cython >= 0.29.13 for Python 3.8 support and
+OpenBLAS >= 3.7 to avoid problems on the Skylake architecture. The NumPy wheels
+on PyPI are built from the OpenBLAS development branch in order to avoid those
+problems.
+
+
+Contributors
+============
+
+A total of 17 people contributed to this release.  People with a "+" by their
+names contributed a patch for the first time.
+
+* Alexander Jung +
+* Allan Haldane
+* Charles Harris
+* Eric Wieser
+* Giuseppe Cuccu +
+* Hiroyuki V. Yamazaki
+* JĂ©rĂ©mie du Boisberranger
+* Kmol Yuan +
+* Matti Picus
+* Max Bolingbroke +
+* Maxwell Aladago +
+* Oleksandr Pavlyk
+* Peter Andreas Entschev
+* Sergei Lebedev
+* Seth Troisi +
+* Vladimir Pershin +
+* Warren Weckesser
+
+
+Pull requests merged
+====================
+
+A total of 24 pull requests were merged for this release.
+
+* `#14156 <https://github.com/numpy/numpy/pull/14156>`__: TST: Allow fuss in testing strided/non-strided exp/log loops
+* `#14157 <https://github.com/numpy/numpy/pull/14157>`__: BUG: avx2_scalef_ps must be static
+* `#14158 <https://github.com/numpy/numpy/pull/14158>`__: BUG: Remove stray print that causes a SystemError on python 3.7.
+* `#14159 <https://github.com/numpy/numpy/pull/14159>`__: BUG: Fix DeprecationWarning in python 3.8.
+* `#14160 <https://github.com/numpy/numpy/pull/14160>`__: BLD: Add missing gcd/lcm definitions to npy_math.h
+* `#14161 <https://github.com/numpy/numpy/pull/14161>`__: DOC, BUILD: cleanups and fix (again) 'build dist'
+* `#14166 <https://github.com/numpy/numpy/pull/14166>`__: TST: Add 3.8-dev to travisCI testing.
+* `#14194 <https://github.com/numpy/numpy/pull/14194>`__: BUG: Remove the broken clip wrapper (Backport)
+* `#14198 <https://github.com/numpy/numpy/pull/14198>`__: DOC: Fix hermitian argument docs in svd.
+* `#14199 <https://github.com/numpy/numpy/pull/14199>`__: MAINT: Workaround for Intel compiler bug leading to failing test
+* `#14200 <https://github.com/numpy/numpy/pull/14200>`__: TST: Clean up of test_pocketfft.py
+* `#14201 <https://github.com/numpy/numpy/pull/14201>`__: BUG: Make advanced indexing result on read-only subclass writeable...
+* `#14236 <https://github.com/numpy/numpy/pull/14236>`__: BUG: Fixed default BitGenerator name
+* `#14237 <https://github.com/numpy/numpy/pull/14237>`__: ENH: add c-imported modules for freeze analysis in np.random
+* `#14296 <https://github.com/numpy/numpy/pull/14296>`__: TST: Pin pytest version to 5.0.1
+* `#14301 <https://github.com/numpy/numpy/pull/14301>`__: BUG: Fix leak in the f2py-generated module init and `PyMem_Del`...
+* `#14302 <https://github.com/numpy/numpy/pull/14302>`__: BUG: Fix formatting error in exception message
+* `#14307 <https://github.com/numpy/numpy/pull/14307>`__: MAINT: random: Match type of SeedSequence.pool_size to DEFAULT_POOL_SIZE.
+* `#14308 <https://github.com/numpy/numpy/pull/14308>`__: BUG: Fix numpy.random bug in platform detection
+* `#14309 <https://github.com/numpy/numpy/pull/14309>`__: ENH: Enable huge pages in all Linux builds
+* `#14330 <https://github.com/numpy/numpy/pull/14330>`__: BUG: Fix segfault in `random.permutation(x)` when x is a string.
+* `#14338 <https://github.com/numpy/numpy/pull/14338>`__: BUG: don't fail when lexsorting some empty arrays (#14228)
+* `#14339 <https://github.com/numpy/numpy/pull/14339>`__: BUG: Fix misuse of .names and .fields in various places (backport...
+* `#14345 <https://github.com/numpy/numpy/pull/14345>`__: BUG: fix behavior of structured_to_unstructured on non-trivial...
+* `#14350 <https://github.com/numpy/numpy/pull/14350>`__: REL: Prepare 1.17.1 release
index f8d83726f03aa50d0c8092ab540717583f29029e..5750e402fec03e766edc5672217ff4a875715084 100644 (file)
@@ -2,6 +2,7 @@
 Release Notes
 *************
 
+.. include:: ../release/1.17.1-notes.rst
 .. include:: ../release/1.17.0-notes.rst
 .. include:: ../release/1.16.4-notes.rst
 .. include:: ../release/1.16.3-notes.rst
index c70718cb6e1f29b224c55816f70f69b8547e4e80..b0ea603e12a44669a66eb96ade68d379d2a8f752 100644 (file)
@@ -459,7 +459,7 @@ def _getfield_is_safe(oldtype, newtype, offset):
     if newtype.hasobject or oldtype.hasobject:
         if offset == 0 and newtype == oldtype:
             return
-        if oldtype.names:
+        if oldtype.names is not None:
             for name in oldtype.names:
                 if (oldtype.fields[name][1] == offset and
                         oldtype.fields[name][0] == newtype):
index 3e8cdf6ab71747ef1ff6125926c19c74aaebeaeb..8251beae86b68fbf274f03ba62d17d280e7cbff3 100644 (file)
@@ -682,7 +682,7 @@ def array2string(a, max_line_width=None, precision=None,
         if style is np._NoValue:
             style = repr
 
-        if a.shape == () and not a.dtype.names:
+        if a.shape == () and a.dtype.names is None:
             return style(a.item())
     elif style is not np._NoValue:
         # Deprecation 11-9-2017  v1.14
index dfb8ff5266ff5fef17062355abed4e4719383d67..6a78ff3c2b545d3cd5c2395bf11d29f4ca193420 100644 (file)
@@ -113,37 +113,54 @@ NPY_INLINE static float __npy_nzerof(void)
 #define NPY_SQRT2l    1.414213562373095048801688724209698079L /* sqrt(2) */
 #define NPY_SQRT1_2l  0.707106781186547524400844362104849039L /* 1/sqrt(2) */
 
-/* 
- * Constants used in vector implementation of exp(x) 
+/*
+ * Constants used in vector implementation of exp(x)
  */
 #define NPY_RINT_CVT_MAGICf 0x1.800000p+23f
 #define NPY_CODY_WAITE_LOGE_2_HIGHf -6.93145752e-1f
 #define NPY_CODY_WAITE_LOGE_2_LOWf -1.42860677e-6f
-#define NPY_COEFF_P0_EXPf 9.999999999980870924916e-01f                                 
-#define NPY_COEFF_P1_EXPf 7.257664613233124478488e-01f                                 
-#define NPY_COEFF_P2_EXPf 2.473615434895520810817e-01f                                 
-#define NPY_COEFF_P3_EXPf 5.114512081637298353406e-02f                                 
-#define NPY_COEFF_P4_EXPf 6.757896990527504603057e-03f                                 
-#define NPY_COEFF_P5_EXPf 5.082762527590693718096e-04f                                 
-#define NPY_COEFF_Q0_EXPf 1.000000000000000000000e+00f                                 
-#define NPY_COEFF_Q1_EXPf -2.742335390411667452936e-01f                                
-#define NPY_COEFF_Q2_EXPf 2.159509375685829852307e-02f  
-
-/* 
- * Constants used in vector implementation of log(x) 
+#define NPY_COEFF_P0_EXPf 9.999999999980870924916e-01f
+#define NPY_COEFF_P1_EXPf 7.257664613233124478488e-01f
+#define NPY_COEFF_P2_EXPf 2.473615434895520810817e-01f
+#define NPY_COEFF_P3_EXPf 5.114512081637298353406e-02f
+#define NPY_COEFF_P4_EXPf 6.757896990527504603057e-03f
+#define NPY_COEFF_P5_EXPf 5.082762527590693718096e-04f
+#define NPY_COEFF_Q0_EXPf 1.000000000000000000000e+00f
+#define NPY_COEFF_Q1_EXPf -2.742335390411667452936e-01f
+#define NPY_COEFF_Q2_EXPf 2.159509375685829852307e-02f
+
+/*
+ * Constants used in vector implementation of log(x)
+ */
+#define NPY_COEFF_P0_LOGf 0.000000000000000000000e+00f
+#define NPY_COEFF_P1_LOGf 9.999999999999998702752e-01f
+#define NPY_COEFF_P2_LOGf 2.112677543073053063722e+00f
+#define NPY_COEFF_P3_LOGf 1.480000633576506585156e+00f
+#define NPY_COEFF_P4_LOGf 3.808837741388407920751e-01f
+#define NPY_COEFF_P5_LOGf 2.589979117907922693523e-02f
+#define NPY_COEFF_Q0_LOGf 1.000000000000000000000e+00f
+#define NPY_COEFF_Q1_LOGf 2.612677543073109236779e+00f
+#define NPY_COEFF_Q2_LOGf 2.453006071784736363091e+00f
+#define NPY_COEFF_Q3_LOGf 9.864942958519418960339e-01f
+#define NPY_COEFF_Q4_LOGf 1.546476374983906719538e-01f
+#define NPY_COEFF_Q5_LOGf 5.875095403124574342950e-03f
+
+/*
+ * Integer functions.
  */
-#define NPY_COEFF_P0_LOGf 0.000000000000000000000e+00f                          
-#define NPY_COEFF_P1_LOGf 9.999999999999998702752e-01f                          
-#define NPY_COEFF_P2_LOGf 2.112677543073053063722e+00f                          
-#define NPY_COEFF_P3_LOGf 1.480000633576506585156e+00f                          
-#define NPY_COEFF_P4_LOGf 3.808837741388407920751e-01f                          
-#define NPY_COEFF_P5_LOGf 2.589979117907922693523e-02f                          
-#define NPY_COEFF_Q0_LOGf 1.000000000000000000000e+00f                          
-#define NPY_COEFF_Q1_LOGf 2.612677543073109236779e+00f                          
-#define NPY_COEFF_Q2_LOGf 2.453006071784736363091e+00f                          
-#define NPY_COEFF_Q3_LOGf 9.864942958519418960339e-01f                          
-#define NPY_COEFF_Q4_LOGf 1.546476374983906719538e-01f                          
-#define NPY_COEFF_Q5_LOGf 5.875095403124574342950e-03f 
+NPY_INPLACE npy_uint npy_gcdu(npy_uint a, npy_uint b);
+NPY_INPLACE npy_uint npy_lcmu(npy_uint a, npy_uint b);
+NPY_INPLACE npy_ulong npy_gcdul(npy_ulong a, npy_ulong b);
+NPY_INPLACE npy_ulong npy_lcmul(npy_ulong a, npy_ulong b);
+NPY_INPLACE npy_ulonglong npy_gcdull(npy_ulonglong a, npy_ulonglong b);
+NPY_INPLACE npy_ulonglong npy_lcmull(npy_ulonglong a, npy_ulonglong b);
+
+NPY_INPLACE npy_int npy_gcd(npy_int a, npy_int b);
+NPY_INPLACE npy_int npy_lcm(npy_int a, npy_int b);
+NPY_INPLACE npy_long npy_gcdl(npy_long a, npy_long b);
+NPY_INPLACE npy_long npy_lcml(npy_long a, npy_long b);
+NPY_INPLACE npy_longlong npy_gcdll(npy_longlong a, npy_longlong b);
+NPY_INPLACE npy_longlong npy_lcmll(npy_longlong a, npy_longlong b);
 
 /*
  * C99 double math funcs
index 659ffa42bb2f668c59508e7d5a433b1c666824cf..2b31625c355eec13476ef63fdd542e8893585b1a 100644 (file)
@@ -268,8 +268,8 @@ class record(nt.void):
             except AttributeError:
                 #happens if field is Object type
                 return obj
-            if dt.fields:
-                return obj.view((self.__class__, obj.dtype.fields))
+            if dt.names is not None:
+                return obj.view((self.__class__, obj.dtype))
             return obj
         else:
             raise AttributeError("'record' object has no "
@@ -293,8 +293,8 @@ class record(nt.void):
         obj = nt.void.__getitem__(self, indx)
 
         # copy behavior of record.__getattribute__,
-        if isinstance(obj, nt.void) and obj.dtype.fields:
-            return obj.view((self.__class__, obj.dtype.fields))
+        if isinstance(obj, nt.void) and obj.dtype.names is not None:
+            return obj.view((self.__class__, obj.dtype))
         else:
             # return a single element
             return obj
@@ -444,7 +444,7 @@ class recarray(ndarray):
         return self
 
     def __array_finalize__(self, obj):
-        if self.dtype.type is not record and self.dtype.fields:
+        if self.dtype.type is not record and self.dtype.names is not None:
             # if self.dtype is not np.record, invoke __setattr__ which will
             # convert it to a record if it is a void dtype.
             self.dtype = self.dtype
@@ -472,7 +472,7 @@ class recarray(ndarray):
         # with void type convert it to the same dtype.type (eg to preserve
         # numpy.record type if present), since nested structured fields do not
         # inherit type. Don't do this for non-void structures though.
-        if obj.dtype.fields:
+        if obj.dtype.names is not None:
             if issubclass(obj.dtype.type, nt.void):
                 return obj.view(dtype=(self.dtype.type, obj.dtype))
             return obj
@@ -487,7 +487,7 @@ class recarray(ndarray):
 
         # Automatically convert (void) structured types to records
         # (but not non-void structures, subarrays, or non-structured voids)
-        if attr == 'dtype' and issubclass(val.type, nt.void) and val.fields:
+        if attr == 'dtype' and issubclass(val.type, nt.void) and val.names is not None:
             val = sb.dtype((record, val))
 
         newattr = attr not in self.__dict__
@@ -521,7 +521,7 @@ class recarray(ndarray):
         # copy behavior of getattr, except that here
         # we might also be returning a single element
         if isinstance(obj, ndarray):
-            if obj.dtype.fields:
+            if obj.dtype.names is not None:
                 obj = obj.view(type(self))
                 if issubclass(obj.dtype.type, nt.void):
                     return obj.view(dtype=(self.dtype.type, obj.dtype))
@@ -577,7 +577,7 @@ class recarray(ndarray):
 
         if val is None:
             obj = self.getfield(*res)
-            if obj.dtype.fields:
+            if obj.dtype.names is not None:
                 return obj
             return obj.view(ndarray)
         else:
index addc9f006683faa7ad5655c354948cad43794ae3..a7f34cbe5821dc573e2155d28c9e7e355753fafc 100644 (file)
 
 #include <assert.h>
 
-#ifdef HAVE_SYS_MMAN_H
+#ifdef NPY_OS_LINUX
 #include <sys/mman.h>
-#if defined MADV_HUGEPAGE && defined HAVE_MADVISE
-#define HAVE_MADV_HUGEPAGE
+#ifndef MADV_HUGEPAGE
+/*
+ * Use code 14 (MADV_HUGEPAGE) if it isn't defined. This gives a chance of
+ * enabling huge pages even if built with linux kernel < 2.6.38
+ */
+#define MADV_HUGEPAGE 14
 #endif
 #endif
 
@@ -74,11 +78,15 @@ _npy_alloc_cache(npy_uintp nelem, npy_uintp esz, npy_uint msz,
 #ifdef _PyPyGC_AddMemoryPressure
         _PyPyPyGC_AddMemoryPressure(nelem * esz);
 #endif
-#ifdef HAVE_MADV_HUGEPAGE
+#ifdef NPY_OS_LINUX
         /* allow kernel allocating huge pages for large arrays */
         if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u)))) {
             npy_uintp offset = 4096u - (npy_uintp)p % (4096u);
             npy_uintp length = nelem * esz - offset;
+            /**
+             * Intentionally not checking for errors that may be returned by
+             * older kernel versions; optimistically tries enabling huge pages.
+             */
             madvise((void*)((npy_uintp)p + offset), length, MADV_HUGEPAGE);
         }
 #endif
index dc79bfa091f52e33aa1240e5e5dd5fa5411eb944..c38067681fb637efa5cfa109d8f6973041f8ac7f 100644 (file)
@@ -367,6 +367,18 @@ arr_insert(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
 
 #define LIKELY_IN_CACHE_SIZE 8
 
+#ifdef __INTEL_COMPILER
+#pragma intel optimization_level 0
+#endif
+static NPY_INLINE npy_intp
+_linear_search(const npy_double key, const npy_double *arr, const npy_intp len, const npy_intp i0)
+{
+    npy_intp i;
+
+    for (i = i0; i < len && key >= arr[i]; i++);
+    return i - 1;
+}
+
 /** @brief find index of a sorted array such that arr[i] <= key < arr[i + 1].
  *
  * If an starting index guess is in-range, the array values around this
@@ -406,10 +418,7 @@ binary_search_with_guess(const npy_double key, const npy_double *arr,
      * From above we know key >= arr[0] when we start.
      */
     if (len <= 4) {
-        npy_intp i;
-
-        for (i = 1; i < len && key >= arr[i]; ++i);
-        return i - 1;
+        return _linear_search(key, arr, len, 1);
     }
 
     if (guess > len - 3) {
index f1e4feac2f9171a64f9d7d719bfa34c703471e35..4268b8893ce78d1afa9f24c4b5749eccc82c2656 100644 (file)
@@ -2269,7 +2269,10 @@ convert_pydatetime_to_datetimestruct(PyObject *obj, npy_datetimestruct *out,
             if (tmp == NULL) {
                 return -1;
             }
-            seconds_offset = PyInt_AsLong(tmp);
+            /* Rounding here is no worse than the integer division below.
+             * Only whole minute offsets are supported by numpy anyway.
+             */
+            seconds_offset = (int)PyFloat_AsDouble(tmp);
             if (error_converting(seconds_offset)) {
                 Py_DECREF(tmp);
                 return -1;
index ff85c3fcba31612bb8660c8ec5334eeaa2fb6107..4d22c9ee73ddac835e649fec57025b704a047c97 100644 (file)
@@ -497,9 +497,6 @@ _convert_from_array_descr(PyObject *obj, int align)
             else {
                 ret = PyArray_DescrConverter(PyTuple_GET_ITEM(item, 1), &conv);
             }
-            if (ret == NPY_FAIL) {
-                PyObject_Print(PyTuple_GET_ITEM(item, 1), stderr, 0);
-            }
         }
         else if (PyTuple_GET_SIZE(item) == 3) {
             newobj = PyTuple_GetSlice(item, 1, 3);
@@ -517,6 +514,7 @@ _convert_from_array_descr(PyObject *obj, int align)
         if (ret == NPY_FAIL) {
             goto fail;
         }
+
         if ((PyDict_GetItem(fields, name) != NULL)
              || (title
                  && PyBaseString_Check(title)
index 11c45dce54ab87cbc8e8953dedb4337a74ed0fc3..2dc74732c6482b9448ab2b40be0455f09f6cd85e 100644 (file)
@@ -1456,8 +1456,8 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
 
     /* Now we can check the axis */
     nd = PyArray_NDIM(mps[0]);
-    if ((nd == 0) || (PyArray_SIZE(mps[0]) == 1)) {
-        /* single element case */
+    if ((nd == 0) || (PyArray_SIZE(mps[0]) <= 1)) {
+        /* empty/single element case */
         ret = (PyArrayObject *)PyArray_NewFromDescr(
             &PyArray_Type, PyArray_DescrFromType(NPY_INTP),
             PyArray_NDIM(mps[0]), PyArray_DIMS(mps[0]), NULL, NULL,
@@ -1466,7 +1466,9 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
         if (ret == NULL) {
             goto fail;
         }
-        *((npy_intp *)(PyArray_DATA(ret))) = 0;
+        if (PyArray_SIZE(mps[0]) > 0) {
+            *((npy_intp *)(PyArray_DATA(ret))) = 0;
+        }
         goto finish;
     }
     if (check_and_adjust_axis(&axis, nd) < 0) {
@@ -1516,19 +1518,28 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
         char *valbuffer, *indbuffer;
         int *swaps;
 
-        if (N == 0 || maxelsize == 0 || sizeof(npy_intp) == 0) {
-            goto fail;
+        assert(N > 0);  /* Guaranteed and assumed by indbuffer */
+        int valbufsize = N * maxelsize;
+        if (NPY_UNLIKELY(valbufsize) == 0) {
+            valbufsize = 1;  /* Ensure allocation is not empty */
         }
-        valbuffer = PyDataMem_NEW(N * maxelsize);
+
+        valbuffer = PyDataMem_NEW(valbufsize);
         if (valbuffer == NULL) {
             goto fail;
         }
         indbuffer = PyDataMem_NEW(N * sizeof(npy_intp));
         if (indbuffer == NULL) {
+            PyDataMem_FREE(valbuffer);
+            goto fail;
+        }
+        swaps = malloc(NPY_LIKELY(n > 0) ? n * sizeof(int) : 1);
+        if (swaps == NULL) {
+            PyDataMem_FREE(valbuffer);
             PyDataMem_FREE(indbuffer);
             goto fail;
         }
-        swaps = malloc(n*sizeof(int));
+
         for (j = 0; j < n; j++) {
             swaps[j] = PyArray_ISBYTESWAPPED(mps[j]);
         }
@@ -1557,8 +1568,8 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
 #else
                 if (rcode < 0) {
 #endif
-                    npy_free_cache(valbuffer, N * maxelsize);
-                    npy_free_cache(indbuffer, N * sizeof(npy_intp));
+                    PyDataMem_FREE(valbuffer);
+                    PyDataMem_FREE(indbuffer);
                     free(swaps);
                     goto fail;
                 }
index 9e54a2c6468502ad9276a9bc0f567f5ea0be16a8..cc628e47ee136dcc93bdba0104bc4b52b4d8a174 100644 (file)
@@ -1699,7 +1699,7 @@ array_subscript(PyArrayObject *self, PyObject *op)
                 PyArray_SHAPE(tmp_arr),
                 PyArray_STRIDES(tmp_arr),
                 PyArray_BYTES(tmp_arr),
-                PyArray_FLAGS(self),
+                PyArray_FLAGS(tmp_arr),
                 (PyObject *)self, (PyObject *)tmp_arr);
         Py_DECREF(tmp_arr);
         if (result == NULL) {
index 6b07a9d88c92e2c0d9695106c92e8e76f9389a1a..9816a1da446a7ff06fa52b435f2467df5c620d3c 100644 (file)
@@ -1224,7 +1224,7 @@ avx2_get_mantissa(__m256 x)
                         _mm256_castps_si256(x), mantissa_bits), exp_126_bits));
 }
 
-NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
 avx2_scalef_ps(__m256 poly, __m256 quadrant)
 {
     /*
index 6d71fcbd658e487808580f4237ce14f9b8479a91..58ebea024ba7792a86226ba2c43335b1f8823e05 100644 (file)
@@ -101,7 +101,7 @@ class _DeprecationTestCase(object):
                         (self.warning_cls.__name__, warning.category))
         if num is not None and num_found != num:
             msg = "%i warnings found but %i expected." % (len(self.log), num)
-            lst = [str(w.category) for w in self.log]
+            lst = [str(w) for w in self.log]
             raise AssertionError("\n".join([msg] + lst))
 
         with warnings.catch_warnings():
index f7485c3f7c9e1065f163d2b8827b167e7fc9eadc..70a5a246f39b4748a0924680b60e5001029422b9 100644 (file)
@@ -617,6 +617,19 @@ class TestSubclasses(object):
         assert_array_equal(s_bool, a[a > 0])
         assert_array_equal(s_bool.base, a[a > 0])
 
+    def test_fancy_on_read_only(self):
+        # Test that fancy indexing on read-only SubClass does not make a
+        # read-only copy (gh-14132)
+        class SubClass(np.ndarray):
+            pass
+
+        a = np.arange(5)
+        s = a.view(SubClass)
+        s.flags.writeable = False
+        s_fancy = s[[0, 1, 2]]
+        assert_(s_fancy.flags.writeable)
+
+
     def test_finalize_gets_full_info(self):
         # Array finalize should be called on the filled array.
         class SubClass(np.ndarray):
index 14413224eeb94188af477db23cc8b4b477129cb9..c1b794145d1974648cfa9f0f6c0aad0ae629e713 100644 (file)
@@ -444,6 +444,48 @@ class TestRecord(object):
         ]
         arr = np.rec.fromarrays(arrays)  # ValueError?
 
+    @pytest.mark.parametrize('nfields', [0, 1, 2])
+    def test_assign_dtype_attribute(self, nfields):
+        dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields])
+        data = np.zeros(3, dt).view(np.recarray)
+
+        # the original and resulting dtypes differ on whether they are records
+        assert data.dtype.type == np.record
+        assert dt.type != np.record
+
+        # ensure that the dtype remains a record even when assigned
+        data.dtype = dt
+        assert data.dtype.type == np.record
+
+    @pytest.mark.parametrize('nfields', [0, 1, 2])
+    def test_nested_fields_are_records(self, nfields):
+        """ Test that nested structured types are treated as records too """
+        dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields])
+        dt_outer = np.dtype([('inner', dt)])
+
+        data = np.zeros(3, dt_outer).view(np.recarray)
+        assert isinstance(data, np.recarray)
+        assert isinstance(data['inner'], np.recarray)
+
+        data0 = data[0]
+        assert isinstance(data0, np.record)
+        assert isinstance(data0['inner'], np.record)
+
+    def test_nested_dtype_padding(self):
+        """ test that trailing padding is preserved """
+        # construct a dtype with padding at the end
+        dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)])
+        dt_padded_end = dt[['a', 'b']]
+        assert dt_padded_end.itemsize == dt.itemsize
+
+        dt_outer = np.dtype([('inner', dt_padded_end)])
+
+        data = np.zeros(3, dt_outer).view(np.recarray)
+        assert_equal(data['inner'].dtype, dt_padded_end)
+
+        data0 = data[0]
+        assert_equal(data0['inner'].dtype, dt_padded_end)
+
 
 def test_find_duplicate():
     l1 = [1, 2, 3, 4, 5, 6]
index 4e48c82b7d75f9145d20684d236d496f49e97393..794d30287bc2ece6b4a0e1666e47022d2e658a34 100644 (file)
@@ -436,6 +436,32 @@ class TestRegression(object):
 
         assert_raises(KeyError, np.lexsort, BuggySequence())
 
+    def test_lexsort_zerolen_custom_strides(self):
+        # Ticket #14228
+        xs = np.array([], dtype='i8')
+        assert xs.strides == (8,)
+        assert np.lexsort((xs,)).shape[0] == 0 # Works
+
+        xs.strides = (16,)
+        assert np.lexsort((xs,)).shape[0] == 0 # Was: MemoryError
+
+    def test_lexsort_zerolen_custom_strides_2d(self):
+        xs = np.array([], dtype='i8')
+
+        xs.shape = (0, 2)
+        xs.strides = (16, 16)
+        assert np.lexsort((xs,), axis=0).shape[0] == 0
+
+        xs.shape = (2, 0)
+        xs.strides = (16, 16)
+        assert np.lexsort((xs,), axis=0).shape[0] == 2
+
+    def test_lexsort_zerolen_element(self):
+        dt = np.dtype([])  # a void dtype with no fields
+        xs = np.empty(4, dt)
+
+        assert np.lexsort((xs,)).shape[0] == xs.shape[0]
+
     def test_pickle_py2_bytes_encoding(self):
         # Check that arrays and scalars pickled on Py2 are
         # unpickleable on Py3 using encoding='bytes'
@@ -468,7 +494,7 @@ class TestRegression(object):
                 result = pickle.loads(data, encoding='bytes')
                 assert_equal(result, original)
 
-                if isinstance(result, np.ndarray) and result.dtype.names:
+                if isinstance(result, np.ndarray) and result.dtype.names is not None:
                     for name in result.dtype.names:
                         assert_(isinstance(name, str))
 
index cd2034d9cee97d09a20bb4ade4918414613a3420..1d93f9ac0260d42347f8eb2567117dec9d963fff 100644 (file)
@@ -14,7 +14,7 @@ from numpy.testing import (
     assert_, assert_equal, assert_raises, assert_raises_regex,
     assert_array_equal, assert_almost_equal, assert_array_almost_equal,
     assert_array_max_ulp, assert_allclose, assert_no_warnings, suppress_warnings,
-    _gen_alignment_data
+    _gen_alignment_data, assert_array_almost_equal_nulp
     )
 
 def on_powerpc():
@@ -700,8 +700,8 @@ class TestExpLogFloat32(object):
             exp_true = np.exp(x_f32)
             log_true = np.log(x_f32)
             for jj in strides:
-                assert_equal(np.exp(x_f32[::jj]), exp_true[::jj])
-                assert_equal(np.log(x_f32[::jj]), log_true[::jj])
+                assert_array_almost_equal_nulp(np.exp(x_f32[::jj]), exp_true[::jj], nulp=2)
+                assert_array_almost_equal_nulp(np.log(x_f32[::jj]), log_true[::jj], nulp=2)
 
 class TestLogAddExp(_FilterInvalids):
     def test_logaddexp_values(self):
index 55b0d721c4280b57df8b875151c4fb58b6c2ef7a..02490a1c08091c5cb11a17929cf25f8f14104080 100644 (file)
@@ -321,7 +321,7 @@ def ndpointer(dtype=None, ndim=None, shape=None, flags=None):
     # produce a name for the new type
     if dtype is None:
         name = 'any'
-    elif dtype.names:
+    elif dtype.names is not None:
         name = str(id(dtype))
     else:
         name = dtype.str
old mode 100644 (file)
new mode 100755 (executable)
index 6769f1b..1b41498
@@ -202,7 +202,7 @@ PyMODINIT_FUNC PyInit_#modulename#(void) {
 PyMODINIT_FUNC init#modulename#(void) {
 #endif
 \tint i;
-\tPyObject *m,*d, *s;
+\tPyObject *m,*d, *s, *tmp;
 #if PY_VERSION_HEX >= 0x03000000
 \tm = #modulename#_module = PyModule_Create(&moduledef);
 #else
@@ -224,8 +224,11 @@ PyMODINIT_FUNC init#modulename#(void) {
 \tPyDict_SetItemString(d, \"__doc__\", s);
 \t#modulename#_error = PyErr_NewException (\"#modulename#.error\", NULL, NULL);
 \tPy_DECREF(s);
-\tfor(i=0;f2py_routine_defs[i].name!=NULL;i++)
-\t\tPyDict_SetItemString(d, f2py_routine_defs[i].name,PyFortranObject_NewAsAttr(&f2py_routine_defs[i]));
+\tfor(i=0;f2py_routine_defs[i].name!=NULL;i++) {
+\t\ttmp = PyFortranObject_NewAsAttr(&f2py_routine_defs[i]);
+\t\tPyDict_SetItemString(d, f2py_routine_defs[i].name, tmp);
+\t\tPy_DECREF(tmp);
+\t}
 #initf2pywraphooks#
 #initf90modhooks#
 #initcommonhooks#
index 4a981bf558ab8cc89f92217987235c4251b00a9d..b55385b5069c228788a01437c963707d159deac9 100644 (file)
@@ -80,7 +80,10 @@ PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module
     PyFortranObject *fp = NULL;
     fp = PyObject_New(PyFortranObject, &PyFortran_Type);
     if (fp == NULL) return NULL;
-    if ((fp->dict = PyDict_New())==NULL) return NULL;
+    if ((fp->dict = PyDict_New())==NULL) {
+        PyObject_Del(fp);
+        return NULL;
+    }
     fp->len = 1;
     fp->defs = defs;
     return (PyObject *)fp;
@@ -91,7 +94,7 @@ PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module
 static void
 fortran_dealloc(PyFortranObject *fp) {
     Py_XDECREF(fp->dict);
-    PyMem_Del(fp);
+    PyObject_Del(fp);
 }
 
 
index db185cb21d1683d77154e479914736f3e7892945..7a06d4c45148bd3b417a0f76cb8dd4deba3c9d72 100644 (file)
@@ -4,7 +4,7 @@ import numpy as np
 import pytest
 from numpy.random import random
 from numpy.testing import (
-        assert_array_almost_equal, assert_array_equal, assert_raises,
+        assert_array_equal, assert_raises, assert_allclose
         )
 import threading
 import sys
@@ -34,109 +34,111 @@ class TestFFT1D(object):
         x = random(maxlen) + 1j*random(maxlen)
         xr = random(maxlen)
         for i in range(1,maxlen):
-            assert_array_almost_equal(np.fft.ifft(np.fft.fft(x[0:i])), x[0:i],
-                                      decimal=12)
-            assert_array_almost_equal(np.fft.irfft(np.fft.rfft(xr[0:i]),i),
-                                      xr[0:i], decimal=12)
+            assert_allclose(np.fft.ifft(np.fft.fft(x[0:i])), x[0:i],
+                            atol=1e-12)
+            assert_allclose(np.fft.irfft(np.fft.rfft(xr[0:i]),i),
+                            xr[0:i], atol=1e-12)
 
     def test_fft(self):
         x = random(30) + 1j*random(30)
-        assert_array_almost_equal(fft1(x), np.fft.fft(x))
-        assert_array_almost_equal(fft1(x) / np.sqrt(30),
-                                  np.fft.fft(x, norm="ortho"))
+        assert_allclose(fft1(x), np.fft.fft(x), atol=1e-6)
+        assert_allclose(fft1(x) / np.sqrt(30),
+                        np.fft.fft(x, norm="ortho"), atol=1e-6)
 
     def test_ifft(self):
         x = random(30) + 1j*random(30)
-        assert_array_almost_equal(x, np.fft.ifft(np.fft.fft(x)))
-        assert_array_almost_equal(
-            x, np.fft.ifft(np.fft.fft(x, norm="ortho"), norm="ortho"))
+        assert_allclose(x, np.fft.ifft(np.fft.fft(x)), atol=1e-6)
+        assert_allclose(
+            x, np.fft.ifft(np.fft.fft(x, norm="ortho"), norm="ortho"),
+            atol=1e-6)
 
     def test_fft2(self):
         x = random((30, 20)) + 1j*random((30, 20))
-        assert_array_almost_equal(np.fft.fft(np.fft.fft(x, axis=1), axis=0),
-                                  np.fft.fft2(x))
-        assert_array_almost_equal(np.fft.fft2(x) / np.sqrt(30 * 20),
-                                  np.fft.fft2(x, norm="ortho"))
+        assert_allclose(np.fft.fft(np.fft.fft(x, axis=1), axis=0),
+                        np.fft.fft2(x), atol=1e-6)
+        assert_allclose(np.fft.fft2(x) / np.sqrt(30 * 20),
+                        np.fft.fft2(x, norm="ortho"), atol=1e-6)
 
     def test_ifft2(self):
         x = random((30, 20)) + 1j*random((30, 20))
-        assert_array_almost_equal(np.fft.ifft(np.fft.ifft(x, axis=1), axis=0),
-                                  np.fft.ifft2(x))
-        assert_array_almost_equal(np.fft.ifft2(x) * np.sqrt(30 * 20),
-                                  np.fft.ifft2(x, norm="ortho"))
+        assert_allclose(np.fft.ifft(np.fft.ifft(x, axis=1), axis=0),
+                        np.fft.ifft2(x), atol=1e-6)
+        assert_allclose(np.fft.ifft2(x) * np.sqrt(30 * 20),
+                        np.fft.ifft2(x, norm="ortho"), atol=1e-6)
 
     def test_fftn(self):
         x = random((30, 20, 10)) + 1j*random((30, 20, 10))
-        assert_array_almost_equal(
+        assert_allclose(
             np.fft.fft(np.fft.fft(np.fft.fft(x, axis=2), axis=1), axis=0),
-            np.fft.fftn(x))
-        assert_array_almost_equal(np.fft.fftn(x) / np.sqrt(30 * 20 * 10),
-                                  np.fft.fftn(x, norm="ortho"))
+            np.fft.fftn(x), atol=1e-6)
+        assert_allclose(np.fft.fftn(x) / np.sqrt(30 * 20 * 10),
+                        np.fft.fftn(x, norm="ortho"), atol=1e-6)
 
     def test_ifftn(self):
         x = random((30, 20, 10)) + 1j*random((30, 20, 10))
-        assert_array_almost_equal(
+        assert_allclose(
             np.fft.ifft(np.fft.ifft(np.fft.ifft(x, axis=2), axis=1), axis=0),
-            np.fft.ifftn(x))
-        assert_array_almost_equal(np.fft.ifftn(x) * np.sqrt(30 * 20 * 10),
-                                  np.fft.ifftn(x, norm="ortho"))
+            np.fft.ifftn(x), atol=1e-6)
+        assert_allclose(np.fft.ifftn(x) * np.sqrt(30 * 20 * 10),
+                        np.fft.ifftn(x, norm="ortho"), atol=1e-6)
 
     def test_rfft(self):
         x = random(30)
         for n in [x.size, 2*x.size]:
             for norm in [None, 'ortho']:
-                assert_array_almost_equal(
+                assert_allclose(
                     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"))
+                    np.fft.rfft(x, n=n, norm=norm), atol=1e-6)
+            assert_allclose(
+                np.fft.rfft(x, n=n) / np.sqrt(n),
+                np.fft.rfft(x, n=n, norm="ortho"), atol=1e-6)
 
     def test_irfft(self):
         x = random(30)
-        assert_array_almost_equal(x, np.fft.irfft(np.fft.rfft(x)))
-        assert_array_almost_equal(
-            x, np.fft.irfft(np.fft.rfft(x, norm="ortho"), norm="ortho"))
+        assert_allclose(x, np.fft.irfft(np.fft.rfft(x)), atol=1e-6)
+        assert_allclose(
+            x, np.fft.irfft(np.fft.rfft(x, norm="ortho"), norm="ortho"), atol=1e-6)
 
     def test_rfft2(self):
         x = random((30, 20))
-        assert_array_almost_equal(np.fft.fft2(x)[:, :11], np.fft.rfft2(x))
-        assert_array_almost_equal(np.fft.rfft2(x) / np.sqrt(30 * 20),
-                                  np.fft.rfft2(x, norm="ortho"))
+        assert_allclose(np.fft.fft2(x)[:, :11], np.fft.rfft2(x), atol=1e-6)
+        assert_allclose(np.fft.rfft2(x) / np.sqrt(30 * 20),
+                        np.fft.rfft2(x, norm="ortho"), atol=1e-6)
 
     def test_irfft2(self):
         x = random((30, 20))
-        assert_array_almost_equal(x, np.fft.irfft2(np.fft.rfft2(x)))
-        assert_array_almost_equal(
-            x, np.fft.irfft2(np.fft.rfft2(x, norm="ortho"), norm="ortho"))
+        assert_allclose(x, np.fft.irfft2(np.fft.rfft2(x)), atol=1e-6)
+        assert_allclose(
+            x, np.fft.irfft2(np.fft.rfft2(x, norm="ortho"), norm="ortho"), atol=1e-6)
 
     def test_rfftn(self):
         x = random((30, 20, 10))
-        assert_array_almost_equal(np.fft.fftn(x)[:, :, :6], np.fft.rfftn(x))
-        assert_array_almost_equal(np.fft.rfftn(x) / np.sqrt(30 * 20 * 10),
-                                  np.fft.rfftn(x, norm="ortho"))
+        assert_allclose(np.fft.fftn(x)[:, :, :6], np.fft.rfftn(x), atol=1e-6)
+        assert_allclose(np.fft.rfftn(x) / np.sqrt(30 * 20 * 10),
+                        np.fft.rfftn(x, norm="ortho"), atol=1e-6)
 
     def test_irfftn(self):
         x = random((30, 20, 10))
-        assert_array_almost_equal(x, np.fft.irfftn(np.fft.rfftn(x)))
-        assert_array_almost_equal(
-            x, np.fft.irfftn(np.fft.rfftn(x, norm="ortho"), norm="ortho"))
+        assert_allclose(x, np.fft.irfftn(np.fft.rfftn(x)), atol=1e-6)
+        assert_allclose(
+            x, np.fft.irfftn(np.fft.rfftn(x, norm="ortho"), norm="ortho"), atol=1e-6)
 
     def test_hfft(self):
         x = random(14) + 1j*random(14)
         x_herm = np.concatenate((random(1), x, random(1)))
         x = np.concatenate((x_herm, x[::-1].conj()))
-        assert_array_almost_equal(np.fft.fft(x), np.fft.hfft(x_herm))
-        assert_array_almost_equal(np.fft.hfft(x_herm) / np.sqrt(30),
-                                  np.fft.hfft(x_herm, norm="ortho"))
+        assert_allclose(np.fft.fft(x), np.fft.hfft(x_herm), atol=1e-6)
+        assert_allclose(np.fft.hfft(x_herm) / np.sqrt(30),
+                        np.fft.hfft(x_herm, norm="ortho"), atol=1e-6)
 
     def test_ihttf(self):
         x = random(14) + 1j*random(14)
         x_herm = np.concatenate((random(1), x, random(1)))
         x = np.concatenate((x_herm, x[::-1].conj()))
-        assert_array_almost_equal(x_herm, np.fft.ihfft(np.fft.hfft(x_herm)))
-        assert_array_almost_equal(
+        assert_allclose(x_herm, np.fft.ihfft(np.fft.hfft(x_herm)), atol=1e-6)
+        assert_allclose(
             x_herm, np.fft.ihfft(np.fft.hfft(x_herm, norm="ortho"),
-                                 norm="ortho"))
+                                 norm="ortho"), atol=1e-6)
 
     @pytest.mark.parametrize("op", [np.fft.fftn, np.fft.ifftn,
                                     np.fft.rfftn, np.fft.irfftn])
@@ -146,7 +148,7 @@ class TestFFT1D(object):
         for a in axes:
             op_tr = op(np.transpose(x, a))
             tr_op = np.transpose(op(x, axes=a), a)
-            assert_array_almost_equal(op_tr, tr_op)
+            assert_allclose(op_tr, tr_op, atol=1e-6)
 
     def test_all_1d_norm_preserving(self):
         # verify that round-trip transforms are norm-preserving
@@ -164,8 +166,8 @@ class TestFFT1D(object):
                 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))
+                    assert_allclose(x_norm,
+                                    np.linalg.norm(tmp), atol=1e-6)
 
     @pytest.mark.parametrize("dtype", [np.half, np.single, np.double,
                                        np.longdouble])
@@ -173,8 +175,8 @@ class TestFFT1D(object):
         # make sure that all input precisions are accepted and internally
         # converted to 64bit
         x = random(30).astype(dtype)
-        assert_array_almost_equal(np.fft.ifft(np.fft.fft(x)), x)
-        assert_array_almost_equal(np.fft.irfft(np.fft.rfft(x)), x)
+        assert_allclose(np.fft.ifft(np.fft.fft(x)), x, atol=1e-6)
+        assert_allclose(np.fft.irfft(np.fft.rfft(x)), x, atol=1e-6)
 
 
 @pytest.mark.parametrize(
@@ -190,6 +192,8 @@ def test_fft_with_order(dtype, order, fft):
     # non contiguous arrays
     rng = np.random.RandomState(42)
     X = rng.rand(8, 7, 13).astype(dtype, copy=False)
+    # See discussion in pull/14178
+    _tol = 8.0 * np.sqrt(np.log2(X.size)) * np.finfo(X.dtype).eps
     if order == 'F':
         Y = np.asfortranarray(X)
     else:
@@ -201,7 +205,7 @@ def test_fft_with_order(dtype, order, fft):
         for axis in range(3):
             X_res = fft(X, axis=axis)
             Y_res = fft(Y, axis=axis)
-            assert_array_almost_equal(X_res, Y_res)
+            assert_allclose(X_res, Y_res, atol=_tol, rtol=_tol)
     elif fft.__name__.endswith(('fft2', 'fftn')):
         axes = [(0, 1), (1, 2), (0, 2)]
         if fft.__name__.endswith('fftn'):
@@ -209,9 +213,9 @@ def test_fft_with_order(dtype, order, fft):
         for ax in axes:
             X_res = fft(X, axes=ax)
             Y_res = fft(Y, axes=ax)
-            assert_array_almost_equal(X_res, Y_res)
+            assert_allclose(X_res, Y_res, atol=_tol, rtol=_tol)
     else:
-        raise ValueError
+        raise ValueError()
 
 
 class TestFFTThreadSafe(object):
index 0ebd39b8c5fb607dd5bc6fec965bbd4fe0778706..c392929fd8793720d8255cee144915ae0ea27d95 100644 (file)
@@ -121,7 +121,7 @@ def has_nested_fields(ndtype):
 
     """
     for name in ndtype.names or ():
-        if ndtype[name].names:
+        if ndtype[name].names is not None:
             return True
     return False
 
@@ -931,28 +931,27 @@ def easy_dtype(ndtype, names=None, defaultfmt="f%i", **validationargs):
         names = validate(names, nbfields=nbfields, defaultfmt=defaultfmt)
         ndtype = np.dtype(dict(formats=ndtype, names=names))
     else:
-        nbtypes = len(ndtype)
         # Explicit names
         if names is not None:
             validate = NameValidator(**validationargs)
             if isinstance(names, basestring):
                 names = names.split(",")
             # Simple dtype: repeat to match the nb of names
-            if nbtypes == 0:
+            if ndtype.names is None:
                 formats = tuple([ndtype.type] * len(names))
                 names = validate(names, defaultfmt=defaultfmt)
                 ndtype = np.dtype(list(zip(names, formats)))
             # Structured dtype: just validate the names as needed
             else:
-                ndtype.names = validate(names, nbfields=nbtypes,
+                ndtype.names = validate(names, nbfields=len(ndtype.names),
                                         defaultfmt=defaultfmt)
         # No implicit names
-        elif (nbtypes > 0):
+        elif ndtype.names is not None:
             validate = NameValidator(**validationargs)
             # Default initial names : should we change the format ?
-            if ((ndtype.names == tuple("f%i" % i for i in range(nbtypes))) and
+            if ((ndtype.names == tuple("f%i" % i for i in range(len(ndtype.names)))) and
                     (defaultfmt != "f%i")):
-                ndtype.names = validate([''] * nbtypes, defaultfmt=defaultfmt)
+                ndtype.names = validate([''] * len(ndtype.names), defaultfmt=defaultfmt)
             # Explicit initial names : just validate
             else:
                 ndtype.names = validate(ndtype.names, defaultfmt=defaultfmt)
index b9dc444f82f6ed5f70e01a8f6ec93d72fa6e68cd..633ef9ca2b643688d3e3d510e38a83bbad5c9859 100644 (file)
@@ -2168,7 +2168,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
             outputmask = np.array(masks, dtype=mdtype)
     else:
         # Overwrite the initial dtype names if needed
-        if names and dtype.names:
+        if names and dtype.names is not None:
             dtype.names = names
         # Case 1. We have a structured type
         if len(dtype_flat) > 1:
@@ -2218,7 +2218,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
             #
             output = np.array(data, dtype)
             if usemask:
-                if dtype.names:
+                if dtype.names is not None:
                     mdtype = [(_, bool) for _ in dtype.names]
                 else:
                     mdtype = bool
index 6e257bb3f4af12b4549c66e16067717bc48b8c67..40060b41a7dc2f6c213923e721b9144a4c229843 100644 (file)
@@ -72,7 +72,7 @@ def recursive_fill_fields(input, output):
             current = input[field]
         except ValueError:
             continue
-        if current.dtype.names:
+        if current.dtype.names is not None:
             recursive_fill_fields(current, output[field])
         else:
             output[field][:len(current)] = current
@@ -139,11 +139,11 @@ def get_names(adtype):
     names = adtype.names
     for name in names:
         current = adtype[name]
-        if current.names:
+        if current.names is not None:
             listnames.append((name, tuple(get_names(current))))
         else:
             listnames.append(name)
-    return tuple(listnames) or None
+    return tuple(listnames)
 
 
 def get_names_flat(adtype):
@@ -176,9 +176,9 @@ def get_names_flat(adtype):
     for name in names:
         listnames.append(name)
         current = adtype[name]
-        if current.names:
+        if current.names is not None:
             listnames.extend(get_names_flat(current))
-    return tuple(listnames) or None
+    return tuple(listnames)
 
 
 def flatten_descr(ndtype):
@@ -215,8 +215,8 @@ def _zip_dtype(seqarrays, flatten=False):
     else:
         for a in seqarrays:
             current = a.dtype
-            if current.names and len(current.names) <= 1:
-                # special case - dtypes of 0 or 1 field are flattened
+            if current.names is not None and len(current.names) == 1:
+                # special case - dtypes of 1 field are flattened
                 newdtype.extend(_get_fieldspec(current))
             else:
                 newdtype.append(('', current))
@@ -268,7 +268,7 @@ def get_fieldstructure(adtype, lastname=None, parents=None,):
     names = adtype.names
     for name in names:
         current = adtype[name]
-        if current.names:
+        if current.names is not None:
             if lastname:
                 parents[name] = [lastname, ]
             else:
@@ -281,7 +281,7 @@ def get_fieldstructure(adtype, lastname=None, parents=None,):
             elif lastname:
                 lastparent = [lastname, ]
             parents[name] = lastparent or []
-    return parents or None
+    return parents
 
 
 def _izip_fields_flat(iterable):
@@ -435,7 +435,7 @@ def merge_arrays(seqarrays, fill_value=-1, flatten=False,
     if isinstance(seqarrays, (ndarray, np.void)):
         seqdtype = seqarrays.dtype
         # Make sure we have named fields
-        if not seqdtype.names:
+        if seqdtype.names is None:
             seqdtype = np.dtype([('', seqdtype)])
         if not flatten or _zip_dtype((seqarrays,), flatten=True) == seqdtype:
             # Minimal processing needed: just make sure everythng's a-ok
@@ -653,7 +653,7 @@ def rename_fields(base, namemapper):
         for name in ndtype.names:
             newname = namemapper.get(name, name)
             current = ndtype[name]
-            if current.names:
+            if current.names is not None:
                 newdtype.append(
                     (newname, _recursive_rename_fields(current, namemapper))
                     )
@@ -874,16 +874,35 @@ def _get_fields_and_offsets(dt, offset=0):
     scalar fields in the dtype "dt", including nested fields, in left
     to right order.
     """
+
+    # counts up elements in subarrays, including nested subarrays, and returns
+    # base dtype and count
+    def count_elem(dt):
+        count = 1
+        while dt.shape != ():
+            for size in dt.shape:
+                count *= size
+            dt = dt.base
+        return dt, count
+
     fields = []
     for name in dt.names:
         field = dt.fields[name]
-        if field[0].names is None:
-            count = 1
-            for size in field[0].shape:
-                count *= size
-            fields.append((field[0], count, field[1] + offset))
+        f_dt, f_offset = field[0], field[1]
+        f_dt, n = count_elem(f_dt)
+
+        if f_dt.names is None:
+            fields.append((np.dtype((f_dt, (n,))), n, f_offset + offset))
         else:
-            fields.extend(_get_fields_and_offsets(field[0], field[1] + offset))
+            subfields = _get_fields_and_offsets(f_dt, f_offset + offset)
+            size = f_dt.itemsize
+
+            for i in range(n):
+                if i == 0:
+                    # optimization: avoid list comprehension if no subarray
+                    fields.extend(subfields)
+                else:
+                    fields.extend([(d, c, o + i*size) for d, c, o in subfields])
     return fields
 
 
@@ -948,6 +967,12 @@ def structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe'):
 
     fields = _get_fields_and_offsets(arr.dtype)
     n_fields = len(fields)
+    if n_fields == 0 and dtype is None:
+        raise ValueError("arr has no fields. Unable to guess dtype")
+    elif n_fields == 0:
+        # too many bugs elsewhere for this to work now
+        raise NotImplementedError("arr with no fields is not supported")
+
     dts, counts, offsets = zip(*fields)
     names = ['f{}'.format(n) for n in range(n_fields)]
 
@@ -1039,6 +1064,9 @@ def unstructured_to_structured(arr, dtype=None, names=None, align=False,
     if arr.shape == ():
         raise ValueError('arr must have at least one dimension')
     n_elem = arr.shape[-1]
+    if n_elem == 0:
+        # too many bugs elsewhere for this to work now
+        raise NotImplementedError("last axis with size 0 is not supported")
 
     if dtype is None:
         if names is None:
@@ -1051,7 +1079,11 @@ def unstructured_to_structured(arr, dtype=None, names=None, align=False,
             raise ValueError("don't supply both dtype and names")
         # sanity check of the input dtype
         fields = _get_fields_and_offsets(dtype)
-        dts, counts, offsets = zip(*fields)
+        if len(fields) == 0:
+            dts, counts, offsets = [], [], []
+        else:
+            dts, counts, offsets = zip(*fields)
+
         if n_elem != sum(counts):
             raise ValueError('The length of the last dimension of arr must '
                              'be equal to the number of fields in dtype')
index 78f9f85f3de6060d6c5a09b509469e60a304492d..c2d3365a303b5c48a67bcf19bf861d1031c6cd88 100644 (file)
@@ -1565,6 +1565,13 @@ M   33  21.99
             test = np.genfromtxt(TextIO(data), delimiter=";",
                                  dtype=ndtype, converters=converters)
 
+        # nested but empty fields also aren't supported
+        ndtype = [('idx', int), ('code', object), ('nest', [])]
+        with assert_raises_regex(NotImplementedError,
+                                 'Nested fields.* not supported.*'):
+            test = np.genfromtxt(TextIO(data), delimiter=";",
+                                 dtype=ndtype, converters=converters)
+
     def test_userconverters_with_explicit_dtype(self):
         # Test user_converters w/ explicit (standard) dtype
         data = TextIO('skip,skip,2001-01-01,1.0,skip')
index 0126ccaf814ddb4e407433da3254cf9fd2f529ae..0c839d486fe7ca4cdc990f44ed37a98f311e4949 100644 (file)
@@ -115,6 +115,14 @@ class TestRecFunctions(object):
         test = get_names(ndtype)
         assert_equal(test, ('a', ('b', ('ba', 'bb'))))
 
+        ndtype = np.dtype([('a', int), ('b', [])])
+        test = get_names(ndtype)
+        assert_equal(test, ('a', ('b', ())))
+
+        ndtype = np.dtype([])
+        test = get_names(ndtype)
+        assert_equal(test, ())
+
     def test_get_names_flat(self):
         # Test get_names_flat
         ndtype = np.dtype([('A', '|S3'), ('B', float)])
@@ -125,6 +133,14 @@ class TestRecFunctions(object):
         test = get_names_flat(ndtype)
         assert_equal(test, ('a', 'b', 'ba', 'bb'))
 
+        ndtype = np.dtype([('a', int), ('b', [])])
+        test = get_names_flat(ndtype)
+        assert_equal(test, ('a', 'b'))
+
+        ndtype = np.dtype([])
+        test = get_names_flat(ndtype)
+        assert_equal(test, ())
+
     def test_get_fieldstructure(self):
         # Test get_fieldstructure
 
@@ -147,6 +163,11 @@ class TestRecFunctions(object):
                    'BBA': ['B', 'BB'], 'BBB': ['B', 'BB']}
         assert_equal(test, control)
 
+        # 0 fields
+        ndtype = np.dtype([])
+        test = get_fieldstructure(ndtype)
+        assert_equal(test, {})
+
     def test_find_duplicates(self):
         # Test find_duplicates
         a = ma.array([(2, (2., 'B')), (1, (2., 'B')), (2, (2., 'B')),
@@ -248,7 +269,8 @@ class TestRecFunctions(object):
         # including uniform fields with subarrays unpacked
         d = np.array([(1, [2,  3], [[ 4,  5], [ 6,  7]]),
                       (8, [9, 10], [[11, 12], [13, 14]])],
-                     dtype=[('x0', 'i4'), ('x1', ('i4', 2)), ('x2', ('i4', (2, 2)))])
+                     dtype=[('x0', 'i4'), ('x1', ('i4', 2)),
+                            ('x2', ('i4', (2, 2)))])
         dd = structured_to_unstructured(d)
         ddd = unstructured_to_structured(dd, d.dtype)
         assert_(dd.base is d)
@@ -262,6 +284,40 @@ class TestRecFunctions(object):
         assert_equal(res, np.zeros((10, 6), dtype=int))
 
 
+        # test nested combinations of subarrays and structured arrays, gh-13333
+        def subarray(dt, shape):
+            return np.dtype((dt, shape))
+
+        def structured(*dts):
+            return np.dtype([('x{}'.format(i), dt) for i, dt in enumerate(dts)])
+
+        def inspect(dt, dtype=None):
+            arr = np.zeros((), dt)
+            ret = structured_to_unstructured(arr, dtype=dtype)
+            backarr = unstructured_to_structured(ret, dt)
+            return ret.shape, ret.dtype, backarr.dtype
+
+        dt = structured(subarray(structured(np.int32, np.int32), 3))
+        assert_equal(inspect(dt), ((6,), np.int32, dt))
+
+        dt = structured(subarray(subarray(np.int32, 2), 2))
+        assert_equal(inspect(dt), ((4,), np.int32, dt))
+
+        dt = structured(np.int32)
+        assert_equal(inspect(dt), ((1,), np.int32, dt))
+
+        dt = structured(np.int32, subarray(subarray(np.int32, 2), 2))
+        assert_equal(inspect(dt), ((5,), np.int32, dt))
+
+        dt = structured()
+        assert_raises(ValueError, structured_to_unstructured, np.zeros(3, dt))
+
+        # these currently don't work, but we may make it work in the future
+        assert_raises(NotImplementedError, structured_to_unstructured,
+                                           np.zeros(3, dt), dtype=np.int32)
+        assert_raises(NotImplementedError, unstructured_to_structured,
+                                           np.zeros((3,0), dtype=np.int32))
+
     def test_field_assignment_by_name(self):
         a = np.ones(2, dtype=[('a', 'i4'), ('b', 'f8'), ('c', 'u1')])
         newdt = [('b', 'f4'), ('c', 'u1')]
index c90e25686458434fc9b43a067d66cbb98b537b8f..267c42afb2bc4a5e3bd080bfe99cdbb01483ae68 100644 (file)
@@ -1487,6 +1487,12 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
     compute_uv : bool, optional
         Whether or not to compute `u` and `vh` in addition to `s`.  True
         by default.
+    hermitian : bool, optional
+        If True, `a` is assumed to be Hermitian (symmetric if real-valued),
+        enabling a more efficient method for finding singular values.
+        Defaults to False.
+
+        .. versionadded:: 1.17.0
 
     Returns
     -------
@@ -1504,12 +1510,6 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
         size as those of the input `a`. The size of the last two dimensions
         depends on the value of `full_matrices`. Only returned when
         `compute_uv` is True.
-    hermitian : bool, optional
-        If True, `a` is assumed to be Hermitian (symmetric if real-valued),
-        enabling a more efficient method for finding singular values.
-        Defaults to False.
-
-        .. versionadded:: 1.17.0
 
     Raises
     ------
index a23ae4010a08c7cb4669f1078880d992595ffc0a..33ac936d04bfd43b377ff74e1bb8fa2b90e9cd15 100644 (file)
@@ -5870,7 +5870,6 @@ class MaskedArray(ndarray):
         return out[()]
 
     # Array methods
-    clip = _arraymethod('clip', onmask=False)
     copy = _arraymethod('copy')
     diagonal = _arraymethod('diagonal')
     flatten = _arraymethod('flatten')
index 931a7e8b9a07b4df0e395e05a62ad61e4a5c7604..826fb0f64231d2d605a0370f42dcb93ea7fda535 100644 (file)
@@ -208,7 +208,7 @@ class MaskedRecords(MaskedArray, object):
         _localdict = ndarray.__getattribute__(self, '__dict__')
         _data = ndarray.view(self, _localdict['_baseclass'])
         obj = _data.getfield(*res)
-        if obj.dtype.fields:
+        if obj.dtype.names is not None:
             raise NotImplementedError("MaskedRecords is currently limited to"
                                       "simple records.")
         # Get some special attributes
index fb3f1a810807d6e81e9b7f56d90b14ef14d0f31c..cf11b6096318c5e0f704d17781261a2e50ee8e85 100644 (file)
@@ -3035,6 +3035,13 @@ class TestMaskedArrayMethods(object):
         assert_equal(clipped._data, x.clip(2, 8))
         assert_equal(clipped._data, mx._data.clip(2, 8))
 
+    def test_clip_out(self):
+        # gh-14140
+        a = np.arange(10)
+        m = np.ma.MaskedArray(a, mask=[0, 1] * 5)
+        m.clip(0, 5, out=m)
+        assert_equal(m.mask, [0, 1] * 5)
+
     def test_compress(self):
         # test compress
         a = masked_array([1., 2., 3., 4., 5.], fill_value=9999)
index 2d495d67ebcbd3c5f14f9142dc1b5a185e7738eb..e7eecc5cd2a1f1b2125d8c95a84b7c9bdbb26717 100644 (file)
@@ -177,7 +177,12 @@ __all__ = [
     'zipf',
 ]
 
-from . import mtrand
+# add these for module-freeze analysis (like PyInstaller)
+from . import _pickle
+from . import common
+from . import bounded_integers
+from . import entropy
+
 from .mtrand import *
 from .generator import Generator, default_rng
 from .bit_generator import SeedSequence
index d20a91ced122a29d67e20922207ce388b004e54e..3b58f21e86e83e4be7a2421fca941811c1970a07 100644 (file)
@@ -13,7 +13,7 @@ BitGenerators = {'MT19937': MT19937,
                  }
 
 
-def __generator_ctor(bit_generator_name='mt19937'):
+def __generator_ctor(bit_generator_name='MT19937'):
     """
     Pickling helper function that returns a Generator object
 
@@ -36,7 +36,7 @@ def __generator_ctor(bit_generator_name='mt19937'):
     return Generator(bit_generator())
 
 
-def __bit_generator_ctor(bit_generator_name='mt19937'):
+def __bit_generator_ctor(bit_generator_name='MT19937'):
     """
     Pickling helper function that returns a bit generator object
 
@@ -59,7 +59,7 @@ def __bit_generator_ctor(bit_generator_name='mt19937'):
     return bit_generator()
 
 
-def __randomstate_ctor(bit_generator_name='mt19937'):
+def __randomstate_ctor(bit_generator_name='MT19937'):
     """
     Pickling helper function that returns a legacy RandomState-like object
 
index 79fe692759b0dce5fd171fbcef9af93be42269f7..984033f17eb8f44cf0c06a19fba8987063f39c4b 100644 (file)
@@ -1,5 +1,5 @@
 
-from .common cimport bitgen_t
+from .common cimport bitgen_t, uint32_t
 cimport numpy as np
 
 cdef class BitGenerator():
@@ -14,9 +14,9 @@ cdef class BitGenerator():
 cdef class SeedSequence():
     cdef readonly object entropy
     cdef readonly tuple spawn_key
-    cdef readonly int pool_size
+    cdef readonly uint32_t pool_size
     cdef readonly object pool
-    cdef readonly int n_children_spawned
+    cdef readonly uint32_t n_children_spawned
 
     cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
                      np.ndarray[np.npy_uint32, ndim=1] entropy_array)
index 6694e5e4db029b75a7ae300a3f664b312c6c50a0..eb608af6cf696752238291ed8c946288d24422e7 100644 (file)
@@ -116,7 +116,7 @@ def _coerce_to_uint32_array(x):
     Examples
     --------
     >>> import numpy as np
-    >>> from np.random.bit_generator import _coerce_to_uint32_array
+    >>> from numpy.random.bit_generator import _coerce_to_uint32_array
     >>> _coerce_to_uint32_array(12345)
     array([12345], dtype=uint32)
     >>> _coerce_to_uint32_array('12345')
@@ -458,6 +458,8 @@ cdef class SeedSequence():
         -------
         seqs : list of `SeedSequence` s
         """
+        cdef uint32_t i
+
         seqs = []
         for i in range(self.n_children_spawned,
                        self.n_children_spawned + n_children):
index 6ad5f5b2190632f32b6dfc84be228fc45570ed7b..74cd5f033b0e48b75cc71ed43cc601c7d86a217f 100644 (file)
@@ -227,7 +227,7 @@ cdef check_output(object out, object dtype, object size):
         raise ValueError('Supplied output array is not contiguous, writable or aligned.')
     if out_array.dtype != dtype:
         raise TypeError('Supplied output array has the wrong type. '
-                        'Expected {0}, got {0}'.format(dtype, out_array.dtype))
+                        'Expected {0}, got {1}'.format(np.dtype(dtype), out_array.dtype))
     if size is not None:
         try:
             tup_size = tuple(size)
index c7432d8c16826d329d52ff7bea40713048fd5853..26fd951297245a40956dbc6b407adfbb16eb7acb 100644 (file)
@@ -3919,9 +3919,8 @@ cdef class Generator:
         permutation(x)
 
         Randomly permute a sequence, or return a permuted range.
-
         If `x` is a multi-dimensional array, it is only shuffled along its
-        first index.
+        first index. 
 
         Parameters
         ----------
@@ -3950,13 +3949,20 @@ cdef class Generator:
                [0, 1, 2],
                [3, 4, 5]])
 
+        >>> rng.permutation("abc")
+        Traceback (most recent call last):
+            ...
+        numpy.AxisError: x must be an integer or at least 1-dimensional
         """
+
         if isinstance(x, (int, np.integer)):
             arr = np.arange(x)
             self.shuffle(arr)
             return arr
 
         arr = np.asarray(x)
+        if arr.ndim < 1:
+            raise np.AxisError("x must be an integer or at least 1-dimensional")
 
         # shuffle has fast-path for 1-d
         if arr.ndim == 1:
index 46b6b33888ffb0368839d8a56407a0d1467e4485..eb263cd2dec909b73db2de7fc17c5a720fd5190a 100644 (file)
@@ -4134,6 +4134,7 @@ cdef class RandomState:
         out : ndarray
             Permuted sequence or array range.
 
+
         Examples
         --------
         >>> np.random.permutation(10)
@@ -4149,12 +4150,15 @@ cdef class RandomState:
                [3, 4, 5]])
 
         """
+
         if isinstance(x, (int, np.integer)):
             arr = np.arange(x)
             self.shuffle(arr)
             return arr
 
         arr = np.asarray(x)
+        if arr.ndim < 1:
+            raise IndexError("x must be an integer or at least 1-dimensional")
 
         # shuffle has fast-path for 1-d
         if arr.ndim == 1:
index a1bf3b83c8829e1e3ad153d4e0d104a9f7ac848f..a820d326e0ef4cddb01d103496ee1ee244524531 100644 (file)
@@ -49,8 +49,8 @@ def configuration(parent_package='', top_path=None):
     elif not is_msvc:
         # Some bit generators require c99
         EXTRA_COMPILE_ARGS += ['-std=c99']
-        INTEL_LIKE = any([val in k.lower() for k in platform.uname()
-                          for val in ('x86', 'i686', 'i386', 'amd64')])
+        INTEL_LIKE = any(arch in platform.machine() 
+                         for arch in ('x86', 'i686', 'i386', 'amd64'))
         if INTEL_LIKE:
             # Assumes GCC or GCC-like compiler
             EXTRA_COMPILE_ARGS += ['-msse2']
index a962fe84e1dde0902f041d49c2bac1e00f4c93f8..853d86fbab6c4df8ea6c7f6663d2acc2ed91b88b 100644 (file)
@@ -757,6 +757,19 @@ class TestRandomDist(object):
         arr_2d = np.atleast_2d([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]).T
         actual = random.permutation(arr_2d)
         assert_array_equal(actual, np.atleast_2d(desired).T)
+        
+        bad_x_str = "abcd"
+        assert_raises(np.AxisError, random.permutation, bad_x_str)
+
+        bad_x_float = 1.2
+        assert_raises(np.AxisError, random.permutation, bad_x_float)
+
+        random = Generator(MT19937(self.seed))
+        integer_val = 10
+        desired = [3, 0, 8, 7, 9, 4, 2, 5, 1, 6]
+
+        actual = random.permutation(integer_val)
+        assert_array_equal(actual, desired)
 
     def test_beta(self):
         random = Generator(MT19937(self.seed))
index 3b5a279a32d683cec5397621004f7c0ff657e735..a0edc5c2387bb18014bfdece27481d73d910cb28 100644 (file)
@@ -686,6 +686,21 @@ class TestRandomDist(object):
         actual = random.permutation(arr_2d)
         assert_array_equal(actual, np.atleast_2d(desired).T)
 
+        random.seed(self.seed)
+        bad_x_str = "abcd"
+        assert_raises(IndexError, random.permutation, bad_x_str)
+
+        random.seed(self.seed)
+        bad_x_float = 1.2
+        assert_raises(IndexError, random.permutation, bad_x_float)
+
+        integer_val = 10
+        desired = [9, 0, 8, 5, 1, 3, 4, 7, 6, 2]
+
+        random.seed(self.seed)
+        actual = random.permutation(integer_val)
+        assert_array_equal(actual, desired)
+
     def test_beta(self):
         random.seed(self.seed)
         actual = random.beta(.1, .9, size=(3, 2))
index 9639a632253172edd788201932b97eb934408e8a..b6d8fcf5b4138abb2978c3ea6ddaee2aad939381 100644 (file)
@@ -42,7 +42,7 @@ from paver.easy import Bunch, options, task, sh
 #-----------------------------------
 
 # Path to the release notes
-RELEASE_NOTES = 'doc/release/1.17.0-notes.rst'
+RELEASE_NOTES = 'doc/release/1.17.1-notes.rst'
 
 
 #-------------------------------------------------------
index 8827409704b6023f2e726212311ee97b119013e8..fc5944a4100309c5f94bfc2365b7a46a74bc79d6 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -55,7 +55,7 @@ Operating System :: MacOS
 
 MAJOR               = 1
 MINOR               = 17
-MICRO               = 0
+MICRO               = 1
 ISRELEASED          = True
 VERSION             = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
 
index b1c1f2ca1c37c9cea0f5b6bf4b15730860cece13..c0f8ef8071505aa93d473d05a3ba09d514fa279d 100755 (executable)
@@ -36,6 +36,6 @@ fi
 
 
 pip install --upgrade pip setuptools
-pip install nose pytz cython pytest
+pip install pytz cython pytest==5.0.1
 if [ -n "$USE_ASV" ]; then pip install asv; fi
 popd