diff --git a/doc/changelog/2.4.6-changelog.rst b/doc/changelog/2.4.6-changelog.rst new file mode 100644 index 000000000000..1bcb31fb3e79 --- /dev/null +++ b/doc/changelog/2.4.6-changelog.rst @@ -0,0 +1,21 @@ + +Contributors +============ + +A total of 4 people contributed to this release. People with a "+" by their +names contributed a patch for the first time. + +* !EarlMilktea +* Charles Harris +* Sebastian Berg +* Warren Weckesser + +Pull requests merged +==================== + +A total of 3 pull requests were merged for this release. + +* `#31444 `__: MAINT: Prepare 2.4.x for further development +* `#31453 `__: BUG: Fix regression in ``arr.conj()`` +* `#31459 `__: BUG: ``np.linalg.svd(..., hermitian=True)`` returns non-unitary... + diff --git a/doc/source/release.rst b/doc/source/release.rst index 99104cf0c4ad..cb8bef574af5 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -5,6 +5,7 @@ Release notes .. toctree:: :maxdepth: 2 + 2.4.6 2.4.5 2.4.4 2.4.3 diff --git a/doc/source/release/2.4.6-notes.rst b/doc/source/release/2.4.6-notes.rst new file mode 100644 index 000000000000..f7986f5a48eb --- /dev/null +++ b/doc/source/release/2.4.6-notes.rst @@ -0,0 +1,33 @@ +.. currentmodule:: numpy + +========================= +NumPy 2.4.6 Release Notes +========================= + +NumPy 2.4.6 is a quick release that fixes a regression discovered in the 2.4.5 +release. + +This release supports Python versions 3.11-3.14 + + +Contributors +============ + +A total of 4 people contributed to this release. People with a "+" by their +names contributed a patch for the first time. + +* !EarlMilktea +* Charles Harris +* Sebastian Berg +* Warren Weckesser + + +Pull requests merged +==================== + +A total of 3 pull requests were merged for this release. + +* `#31444 `__: MAINT: Prepare 2.4.x for further development +* `#31453 `__: BUG: Fix regression in ``arr.conj()`` +* `#31459 `__: BUG: ``np.linalg.svd(..., hermitian=True)`` returns non-unitary... + diff --git a/numpy/_core/src/common/raii_utils.hpp b/numpy/_core/src/common/raii_utils.hpp index 1049e97387f0..e92d0eae9269 100644 --- a/numpy/_core/src/common/raii_utils.hpp +++ b/numpy/_core/src/common/raii_utils.hpp @@ -126,11 +126,9 @@ class SaveThreadState // // Instead of // -// Py_INCREF(descr); // npy_string_allocator *allocator = NpyString_acquire_allocator(descr); // [code that uses allocator] // NpyString_release_allocator(allocator); -// Py_DECREF(descr); // // use // @@ -141,19 +139,16 @@ class SaveThreadState // class NpyStringAcquireAllocator { - PyArray_StringDTypeObject *_descr; npy_string_allocator *_allocator; public: - NpyStringAcquireAllocator(PyArray_StringDTypeObject *descr) : _descr(descr) { - Py_INCREF(_descr); - _allocator = NpyString_acquire_allocator(_descr); + NpyStringAcquireAllocator(PyArray_StringDTypeObject *descr) { + _allocator = NpyString_acquire_allocator(descr); } ~NpyStringAcquireAllocator() { NpyString_release_allocator(_allocator); - Py_DECREF(_descr); } NpyStringAcquireAllocator(const NpyStringAcquireAllocator&) = delete; diff --git a/numpy/_core/src/multiarray/calculation.c b/numpy/_core/src/multiarray/calculation.c index a8e74401df76..170aa95fcf7a 100644 --- a/numpy/_core/src/multiarray/calculation.c +++ b/numpy/_core/src/multiarray/calculation.c @@ -829,7 +829,7 @@ NPY_NO_EXPORT PyObject * PyArray_Conjugate(PyArrayObject *self, PyArrayObject *out) { if (PyArray_ISCOMPLEX(self) || PyArray_ISOBJECT(self) || - PyArray_ISUSERDEF(self) || !NPY_DT_is_legacy(PyArray_DESCR(self))) { + PyArray_ISUSERDEF(self) || !NPY_DT_is_legacy(NPY_DTYPE(PyArray_DESCR(self)))) { if (out == NULL) { return PyArray_GenericUnaryFunction(self, n_ops.conjugate); diff --git a/numpy/_core/tests/test_multiarray.py b/numpy/_core/tests/test_multiarray.py index 44ad3651d82d..4df27ee48358 100644 --- a/numpy/_core/tests/test_multiarray.py +++ b/numpy/_core/tests/test_multiarray.py @@ -3918,6 +3918,17 @@ def test_conjugate(self): assert_raises(TypeError, a.conj) assert_raises(TypeError, a.conjugate) + @pytest.mark.parametrize("dtype", ["?", "b", "h", "I"]) + def test_conjugate_view(self, dtype): + a = np.ones(10, dtype=dtype) + assert a.conj() is a + + @pytest.mark.parametrize("dtype", ["S", "U", "M8[ns]"]) + def test_conjugate_error(self, dtype): + a = np.ones(10, dtype=dtype) + with pytest.raises(TypeError, match="cannot conjugate non-numeric dtype"): + a.conj() + def test_conjugate_out(self): # Minimal test for the out argument being passed on correctly # NOTE: The ability to pass `out` is currently undocumented! diff --git a/numpy/_core/tests/test_stringdtype.py b/numpy/_core/tests/test_stringdtype.py index 492894087aa9..40301f21df2a 100644 --- a/numpy/_core/tests/test_stringdtype.py +++ b/numpy/_core/tests/test_stringdtype.py @@ -260,6 +260,7 @@ def test_self_casts(dtype, dtype2, strings): ["this", "is", "an", "array"], ["โ‚ฌ", "", "๐Ÿ˜Š"], ["Aยขโ˜ƒโ‚ฌ ๐Ÿ˜Š", " Aโ˜ƒโ‚ฌยข๐Ÿ˜Š", "โ˜ƒโ‚ฌ๐Ÿ˜Š Aยข", "๐Ÿ˜Šโ˜ƒAยข โ‚ฌ"], + ["short", "12345678"] * 1000, ], ) class TestStringLikeCasts: diff --git a/numpy/linalg/_linalg.py b/numpy/linalg/_linalg.py index 4a1d2c0dce78..951d01f9a299 100644 --- a/numpy/linalg/_linalg.py +++ b/numpy/linalg/_linalg.py @@ -61,7 +61,6 @@ overrides, prod, reciprocal, - sign, single, sort, sqrt, @@ -1810,7 +1809,8 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False): # and related arrays to have the correct order if compute_uv: s, u = eigh(a) - sgn = sign(s) + # avoid zero sign + sgn = np.copysign(1.0, s) s = abs(s) sidx = argsort(s)[..., ::-1] sgn = np.take_along_axis(sgn, sidx, axis=-1) diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 9c06e04a5ec9..0316b435a30c 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -745,6 +745,12 @@ def hermitian(mat): class TestSVDHermitian(SVDHermitianCases, SVDBaseTests): hermitian = True + def test_singular(self): + x = np.array([[1, 0], [0, 0]]) + u, _, vh = linalg.svd(x, hermitian=self.hermitian) + assert_allclose(u @ u.T.conj(), np.eye(2), rtol=1e-14) + assert_allclose(vh @ vh.T.conj(), np.eye(2), rtol=1e-14) + class CondCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase): # cond(x, p) for p in (None, 2, -2) diff --git a/pyproject.toml b/pyproject.toml index f6f9e71cbe0c..98c6830e0e7b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ requires = [ [project] name = "numpy" -version = "2.4.5" +version = "2.4.6" description = "Fundamental package for array computing in Python" authors = [{name = "Travis E. Oliphant et al."}] maintainers = [