Imported Upstream version 1.23.1 upstream/1.23.1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 15 Jul 2022 02:14:57 +0000 (11:14 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 15 Jul 2022 02:14:57 +0000 (11:14 +0900)
18 files changed:
PKG-INFO
doc/changelog/1.23.1-changelog.rst [new file with mode: 0644]
doc/source/release.rst
doc/source/release/1.23.1-notes.rst [new file with mode: 0644]
numpy/_version.py
numpy/core/_machar.py
numpy/core/getlimits.py
numpy/core/include/numpy/npy_math.h
numpy/core/setup.py
numpy/core/src/npysort/binsearch.cpp
numpy/core/tests/test_multiarray.py
numpy/f2py/crackfortran.py
numpy/lib/function_base.py
numpy/lib/npyio.py
numpy/lib/tests/test_function_base.py
numpy/ma/extras.py
numpy/ma/tests/test_extras.py
pavement.py

index 7e71bd59156bb3253a7a339597f617fe7665880f..eec6af782d82c1c2bb594e98b428222e99bfab29 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: numpy
-Version: 1.23.0
+Version: 1.23.1
 Summary:  NumPy is the fundamental package for array computing with Python.
 Home-page: https://www.numpy.org
 Author: Travis E. Oliphant et al.
diff --git a/doc/changelog/1.23.1-changelog.rst b/doc/changelog/1.23.1-changelog.rst
new file mode 100644 (file)
index 0000000..9618bae
--- /dev/null
@@ -0,0 +1,28 @@
+
+Contributors
+============
+
+A total of 7 people contributed to this release.  People with a "+" by their
+names contributed a patch for the first time.
+
+* Charles Harris
+* Matthias Koeppe +
+* Pranab Das +
+* Rohit Goswami
+* Sebastian Berg
+* Serge Guelton
+* Srimukh Sripada +
+
+Pull requests merged
+====================
+
+A total of 8 pull requests were merged for this release.
+
+* `#21866 <https://github.com/numpy/numpy/pull/21866>`__: BUG: Fix discovered MachAr (still used within valgrind)
+* `#21867 <https://github.com/numpy/numpy/pull/21867>`__: BUG: Handle NaNs correctly for float16 during sorting
+* `#21868 <https://github.com/numpy/numpy/pull/21868>`__: BUG: Use ``keepdims`` during normalization in ``np.average`` and...
+* `#21869 <https://github.com/numpy/numpy/pull/21869>`__: DOC: mention changes to ``max_rows`` behaviour in ``np.loadtxt``
+* `#21870 <https://github.com/numpy/numpy/pull/21870>`__: BUG: Reject non integer array-likes with size 1 in delete
+* `#21949 <https://github.com/numpy/numpy/pull/21949>`__: BLD: Make can_link_svml return False for 32bit builds on x86_64
+* `#21951 <https://github.com/numpy/numpy/pull/21951>`__: BUG: Reorder extern "C" to only apply to function declarations...
+* `#21952 <https://github.com/numpy/numpy/pull/21952>`__: BUG: Fix KeyError in crackfortran operator support
index f21b5610d943227e4a98394fa54612a1873a6323..5edebdd5b502f725b165e0912b95e103b2552315 100644 (file)
@@ -5,6 +5,7 @@ Release notes
 .. toctree::
     :maxdepth: 3
 
+    1.23.1 <release/1.23.1-notes>
     1.23.0 <release/1.23.0-notes>
     1.22.4 <release/1.22.4-notes>
     1.22.3 <release/1.22.3-notes>
diff --git a/doc/source/release/1.23.1-notes.rst b/doc/source/release/1.23.1-notes.rst
new file mode 100644 (file)
index 0000000..9b6b04c
--- /dev/null
@@ -0,0 +1,45 @@
+.. currentmodule:: numpy
+
+==========================
+NumPy 1.23.1 Release Notes
+==========================
+
+The NumPy 1.23.1 is a maintenance release that fixes bugs discovered after the
+1.23.0 release. Notable fixes are:
+
+- Fix searchsorted for float16 NaNs
+- Fix compilation on Apple M1
+- Fix KeyError in crackfortran operator support (Slycot)
+
+The Python version supported for this release are 3.8-3.10.
+
+
+Contributors
+============
+
+A total of 7 people contributed to this release.  People with a "+" by their
+names contributed a patch for the first time.
+
+* Charles Harris
+* Matthias Koeppe +
+* Pranab Das +
+* Rohit Goswami
+* Sebastian Berg
+* Serge Guelton
+* Srimukh Sripada +
+
+
+Pull requests merged
+====================
+
+A total of 8 pull requests were merged for this release.
+
+* `#21866 <https://github.com/numpy/numpy/pull/21866>`__: BUG: Fix discovered MachAr (still used within valgrind)
+* `#21867 <https://github.com/numpy/numpy/pull/21867>`__: BUG: Handle NaNs correctly for float16 during sorting
+* `#21868 <https://github.com/numpy/numpy/pull/21868>`__: BUG: Use ``keepdims`` during normalization in ``np.average`` and...
+* `#21869 <https://github.com/numpy/numpy/pull/21869>`__: DOC: mention changes to ``max_rows`` behaviour in ``np.loadtxt``
+* `#21870 <https://github.com/numpy/numpy/pull/21870>`__: BUG: Reject non integer array-likes with size 1 in delete
+* `#21949 <https://github.com/numpy/numpy/pull/21949>`__: BLD: Make can_link_svml return False for 32bit builds on x86_64
+* `#21951 <https://github.com/numpy/numpy/pull/21951>`__: BUG: Reorder extern "C" to only apply to function declarations...
+* `#21952 <https://github.com/numpy/numpy/pull/21952>`__: BUG: Fix KeyError in crackfortran operator support
+
index 38f459ae6bfa0ac6022551feaec7d5ce5afe4744..aa198972cb0b4e58e645b6cfdfeccbaaa15045a2 100644 (file)
@@ -8,11 +8,11 @@ import json
 
 version_json = '''
 {
- "date": "2022-06-22T13:57:27-0600",
+ "date": "2022-07-08T16:31:18-0600",
  "dirty": false,
  "error": null,
- "full-revisionid": "54c52f13713f3d21795926ca4dbb27e16fada171",
- "version": "1.23.0"
+ "full-revisionid": "1f82da745496092d85b402b1703877462a7c2de2",
+ "version": "1.23.1"
 }
 '''  # END VERSION_JSON
 
index ace19a429f7969d2ddd59a425395e2ca74ce2d6d..3cc7db2784de1fce477ab68dfb1776f7a7f4b10f 100644 (file)
@@ -326,7 +326,9 @@ class MachAr:
         self.tiny = self.xmin
         self.huge = self.xmax
         self.smallest_normal = self.xmin
+        self._str_smallest_normal = float_to_str(self.xmin)
         self.smallest_subnormal = float_to_float(smallest_subnormal)
+        self._str_smallest_subnormal = float_to_str(smallest_subnormal)
 
         import math
         self.precision = int(-math.log10(float_to_float(self.eps)))
index ab4a4d2be696de9471d3d7eb84a4218050623a28..4149a5303bc0ab8b793b68d98ea77edfda8deeaf 100644 (file)
@@ -343,8 +343,9 @@ def _get_machar(ftype):
         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),
+        f'Signature {key} for {ftype} does not match any known type: '
+        'falling back to type probe function.\n'
+        'This warnings indicates broken support for the dtype!',
         UserWarning, stacklevel=2)
     return _discovered_machar(ftype)
 
index bead0dc140646f23da966d1f90b383f9d585473b..954c3d0e9e44841e05a5097b3262c453ae6c0846 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_MATH_H_
 #define NUMPY_CORE_INCLUDE_NUMPY_NPY_MATH_H_
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include <numpy/npy_common.h>
 
 #include <math.h>
@@ -21,6 +17,10 @@ extern "C" {
 #endif
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * NAN and INFINITY like macros (same behavior as glibc for NAN, same as C99
  * for INFINITY)
index 6d1d8db4b9391b5df05147581d8b0d61a7fdcf5a..52b51e4b613c10c7dad14ca5550a8e10a9097c22 100644 (file)
@@ -1,9 +1,9 @@
 import os
 import sys
+import sysconfig
 import pickle
 import copy
 import warnings
-import platform
 import textwrap
 import glob
 from os.path import join
@@ -79,9 +79,10 @@ def can_link_svml():
     """
     if NPY_DISABLE_SVML:
         return False
-    machine = platform.machine()
-    system = platform.system()
-    return "x86_64" in machine and system == "Linux"
+    platform = sysconfig.get_platform()
+    return ("x86_64" in platform
+            and "linux" in platform
+            and sys.maxsize > 2**31)
 
 def check_svml_submodule(svmlpath):
     if not os.path.exists(svmlpath + "/README.md"):
index 98d305910d575cca5c5d75dc2f82681266337447..ea07bbb0cd75c6432a0f34d8cdbaa0664b04abcc 100644 (file)
@@ -330,9 +330,9 @@ struct binsearch_t : binsearch_base<arg> {
             npy::bool_tag, npy::byte_tag, npy::ubyte_tag, npy::short_tag,
             npy::ushort_tag, npy::int_tag, npy::uint_tag, npy::long_tag,
             npy::ulong_tag, npy::longlong_tag, npy::ulonglong_tag,
-            npy::half_tag, npy::float_tag, npy::double_tag,
-            npy::longdouble_tag, npy::cfloat_tag, npy::cdouble_tag,
-            npy::clongdouble_tag, npy::datetime_tag, npy::timedelta_tag>;
+            npy::float_tag, npy::double_tag, npy::longdouble_tag, 
+            npy::cfloat_tag, npy::cdouble_tag, npy::clongdouble_tag, 
+            npy::datetime_tag, npy::timedelta_tag, npy::half_tag>;
 
     static constexpr std::array<value_type, taglist::size> map =
             make_binsearch_map(taglist());
index f4454130d7239e7343a1188acd320c57ac0a1b39..ec89f2b37aa8f436a1560b4117fb5f9ba448bc20 100644 (file)
@@ -2388,23 +2388,32 @@ class TestMethods:
         assert_raises(ValueError, d.sort, kind=k)
         assert_raises(ValueError, d.argsort, kind=k)
 
-    def test_searchsorted(self):
-        # test for floats and complex containing nans. The logic is the
-        # same for all float types so only test double types for now.
-        # The search sorted routines use the compare functions for the
-        # array type, so this checks if that is consistent with the sort
-        # order.
-
-        # check double
-        a = np.array([0, 1, np.nan])
-        msg = "Test real searchsorted with nans, side='l'"
+    @pytest.mark.parametrize('a', [
+        np.array([0, 1, np.nan], dtype=np.float16),
+        np.array([0, 1, np.nan], dtype=np.float32),
+        np.array([0, 1, np.nan]),
+    ])
+    def test_searchsorted_floats(self, a):
+        # test for floats arrays containing nans. Explicitly test 
+        # half, single, and double precision floats to verify that
+        # the NaN-handling is correct.
+        msg = "Test real (%s) searchsorted with nans, side='l'" % a.dtype
         b = a.searchsorted(a, side='left')
         assert_equal(b, np.arange(3), msg)
-        msg = "Test real searchsorted with nans, side='r'"
+        msg = "Test real (%s) searchsorted with nans, side='r'" % a.dtype
         b = a.searchsorted(a, side='right')
         assert_equal(b, np.arange(1, 4), msg)
         # check keyword arguments
         a.searchsorted(v=1)
+        x = np.array([0, 1, np.nan], dtype='float32')
+        y = np.searchsorted(x, x[-1])
+        assert_equal(y, 2)
+
+    def test_searchsorted_complex(self):
+        # test for complex arrays containing nans. 
+        # The search sorted routines use the compare functions for the
+        # array type, so this checks if that is consistent with the sort
+        # order.
         # check double complex
         a = np.zeros(9, dtype=np.complex128)
         a.real += [0, 0, 1, 1, 0, 1, np.nan, np.nan, np.nan]
@@ -2423,7 +2432,8 @@ class TestMethods:
         a = np.array([0, 128], dtype='>i4')
         b = a.searchsorted(np.array(128, dtype='>i4'))
         assert_equal(b, 1, msg)
-
+        
+    def test_searchsorted_n_elements(self):
         # Check 0 elements
         a = np.ones(0)
         b = a.searchsorted([0, 1, 2], 'left')
@@ -2443,6 +2453,7 @@ class TestMethods:
         b = a.searchsorted([0, 1, 2], 'right')
         assert_equal(b, [0, 2, 2])
 
+    def test_searchsorted_unaligned_array(self):
         # Test searching unaligned array
         a = np.arange(10)
         aligned = np.empty(a.itemsize * a.size + 1, 'uint8')
@@ -2459,6 +2470,7 @@ class TestMethods:
         b = a.searchsorted(unaligned, 'right')
         assert_equal(b, a + 1)
 
+    def test_searchsorted_resetting(self):
         # Test smart resetting of binsearch indices
         a = np.arange(5)
         b = a.searchsorted([6, 5, 4], 'left')
@@ -2466,6 +2478,7 @@ class TestMethods:
         b = a.searchsorted([6, 5, 4], 'right')
         assert_equal(b, [5, 5, 5])
 
+    def test_searchsorted_type_specific(self):
         # Test all type specific binary search functions
         types = ''.join((np.typecodes['AllInteger'], np.typecodes['AllFloat'],
                          np.typecodes['Datetime'], '?O'))
index 515bdd78777d519119958eea33f80fb3a0585f41..26d4d6d38f4d9289413deb0a5b95c8a52f585d7e 100755 (executable)
@@ -2147,7 +2147,7 @@ def analyzebody(block, args, tab=''):
             as_ = args
         b = postcrack(b, as_, tab=tab + '\t')
         if b['block'] in ['interface', 'abstract interface'] and \
-           not b['body'] and not b['implementedby']:
+           not b['body'] and not b.get('implementedby'):
             if 'f2pyenhancements' not in b:
                 continue
         if b['block'].replace(' ', '') == 'pythonmodule':
index 843e1b85ae6b4509d751776750615b95dea445dc..ca82bb72d1ea54cd546e0fc0691da9a2935b930a 100644 (file)
@@ -542,7 +542,7 @@ def average(a, axis=None, weights=None, returned=False, *,
             wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape)
             wgt = wgt.swapaxes(-1, axis)
 
-        scl = wgt.sum(axis=axis, dtype=result_dtype)
+        scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw)
         if np.any(scl == 0.0):
             raise ZeroDivisionError(
                 "Weights sum to zero, can't be normalized")
@@ -5140,10 +5140,14 @@ def delete(arr, obj, axis=None):
         single_value = False
         _obj = obj
         obj = np.asarray(obj)
+        # `size == 0` to allow empty lists similar to indexing, but (as there)
+        # is really too generic:
         if obj.size == 0 and not isinstance(_obj, np.ndarray):
             obj = obj.astype(intp)
-        elif obj.size == 1 and not isinstance(_obj, bool):
-            obj = obj.astype(intp).reshape(())
+        elif obj.size == 1 and obj.dtype.kind in "ui":
+            # For a size 1 integer array we can use the single-value path
+            # (most dtypes, except boolean, should just fail later).
+            obj = obj.item()
             single_value = True
 
     if single_value:
index 210c0ea94a7e1d8675ca9f9a9c4d9d828f4ed146..52bcf25f88edb7c9720ae73ad3b89efffae0233f 100644 (file)
@@ -1129,10 +1129,17 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
 
         .. versionadded:: 1.14.0
     max_rows : int, optional
-        Read `max_rows` lines of content after `skiprows` lines. The default
-        is to read all the lines.
+        Read `max_rows` rows of content after `skiprows` lines. The default is
+        to read all the rows. Note that empty rows containing no data such as
+        empty lines and comment lines are not counted towards `max_rows`,
+        while such lines are counted in `skiprows`.
 
         .. versionadded:: 1.16.0
+        
+        .. versionchanged:: 1.23.0
+            Lines containing no data, including comment lines (e.g., lines 
+            starting with '#' or as specified via `comments`) are not counted 
+            towards `max_rows`.
     quotechar : unicode character or None, optional
         The character used to denote the start and end of a quoted item.
         Occurrences of the delimiter or comment characters are ignored within
index bdcbef91d8c19e9820a049bcd89ad494d9ffe83b..09e1619560b8b84e4562c7bfe9908b6daa4633f0 100644 (file)
@@ -360,6 +360,18 @@ class TestAverage:
 
         assert_(np.average(y3, weights=w3).dtype == np.result_type(y3, w3))
 
+        # test weights with `keepdims=False` and `keepdims=True`
+        x = np.array([2, 3, 4]).reshape(3, 1)
+        w = np.array([4, 5, 6]).reshape(3, 1)
+
+        actual = np.average(x, weights=w, axis=1, keepdims=False)
+        desired = np.array([2., 3., 4.])
+        assert_array_equal(actual, desired)
+
+        actual = np.average(x, weights=w, axis=1, keepdims=True)
+        desired = np.array([[2.], [3.], [4.]])
+        assert_array_equal(actual, desired)
+
     def test_returned(self):
         y = np.array([[1, 2, 3], [4, 5, 6]])
 
@@ -913,18 +925,39 @@ class TestDelete:
         with pytest.raises(IndexError):
             np.delete([0, 1, 2], np.array([], dtype=float))
 
-    def test_single_item_array(self):
-        a_del = delete(self.a, 1)
-        a_del_arr = delete(self.a, np.array([1]))
-        a_del_lst = delete(self.a, [1])
-        a_del_obj = delete(self.a, np.array([1], dtype=object))
-        assert_equal(a_del, a_del_arr, a_del_lst, a_del_obj)
-
-        nd_a_del = delete(self.nd_a, 1, axis=1)
-        nd_a_del_arr = delete(self.nd_a, np.array([1]), axis=1)
-        nd_a_del_lst = delete(self.nd_a, [1], axis=1)
-        nd_a_del_obj = delete(self.nd_a, np.array([1], dtype=object), axis=1)
-        assert_equal(nd_a_del, nd_a_del_arr, nd_a_del_lst, nd_a_del_obj)
+    @pytest.mark.parametrize("indexer", [np.array([1]), [1]])
+    def test_single_item_array(self, indexer):
+        a_del_int = delete(self.a, 1)
+        a_del = delete(self.a, indexer)
+        assert_equal(a_del_int, a_del)
+
+        nd_a_del_int = delete(self.nd_a, 1, axis=1)
+        nd_a_del = delete(self.nd_a, np.array([1]), axis=1)
+        assert_equal(nd_a_del_int, nd_a_del)
+
+    def test_single_item_array_non_int(self):
+        # Special handling for integer arrays must not affect non-integer ones.
+        # If `False` was cast to `0` it would delete the element:
+        res = delete(np.ones(1), np.array([False]))
+        assert_array_equal(res, np.ones(1))
+
+        # Test the more complicated (with axis) case from gh-21840
+        x = np.ones((3, 1))
+        false_mask = np.array([False], dtype=bool)
+        true_mask = np.array([True], dtype=bool)
+
+        res = delete(x, false_mask, axis=-1)
+        assert_array_equal(res, x)
+        res = delete(x, true_mask, axis=-1)
+        assert_array_equal(res, x[:, :0])
+
+        # Object or e.g. timedeltas should *not* be allowed
+        with pytest.raises(IndexError):
+            delete(np.ones(2), np.array([0], dtype=object))
+
+        with pytest.raises(IndexError):
+            # timedeltas are sometimes "integral, but clearly not allowed:
+            delete(np.ones(2), np.array([0], dtype="m8[ns]"))
 
 
 class TestGradient:
index 641f4746f0589856cff7ed672e869462f60fcf24..c45f160b9b9647787a3fb3e80d4bcf3f091620ba 100644 (file)
@@ -645,7 +645,7 @@ def average(a, axis=None, weights=None, returned=False, *,
             wgt = wgt*(~a.mask)
             wgt.mask |= a.mask
 
-        scl = wgt.sum(axis=axis, dtype=result_dtype)
+        scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw)
         avg = np.multiply(a, wgt,
                           dtype=result_dtype).sum(axis, **keepdims_kw) / scl
 
index 1827edd1f1022f3d5b04416ac8da964c6fff267b..04bf8cfc2284b00f46927ee55b6250589d893be6 100644 (file)
@@ -241,6 +241,15 @@ class TestAverage:
         a2dma = average(a2dm, axis=1)
         assert_equal(a2dma, [1.5, 4.0])
 
+    def test_testAverage4(self):
+        # Test that `keepdims` works with average
+        x = np.array([2, 3, 4]).reshape(3, 1)
+        b = np.ma.array(x, mask=[[False], [False], [True]])
+        w = np.array([4, 5, 6]).reshape(3, 1)
+        actual = average(b, weights=w, axis=1, keepdims=True)
+        desired = masked_array([[2.], [3.], [4.]], [[False], [False], [True]])
+        assert_equal(actual, desired)
+
     def test_onintegers_with_mask(self):
         # Test average on integers with mask
         a = average(array([1, 2]))
index 025489cbd9f5d13a52a5483894817dbea0800781..3812e4a54fb3bd7b8961180f4d659ddad917b18e 100644 (file)
@@ -38,7 +38,7 @@ from paver.easy import Bunch, options, task, sh
 #-----------------------------------
 
 # Path to the release notes
-RELEASE_NOTES = 'doc/source/release/1.23.0-notes.rst'
+RELEASE_NOTES = 'doc/source/release/1.23.1-notes.rst'
 
 
 #-------------------------------------------------------