diff options
45 files changed, 915 insertions, 611 deletions
diff --git a/benchmarks/asv_compare.conf.json.tpl b/benchmarks/asv_compare.conf.json.tpl index 1f339077c..03d13d985 100644 --- a/benchmarks/asv_compare.conf.json.tpl +++ b/benchmarks/asv_compare.conf.json.tpl @@ -78,7 +78,9 @@ "build_command" : [ "python setup.py build {numpy_build_options}", - "PIP_NO_BUILD_ISOLATION=false python -mpip wheel --no-deps --no-index -w {build_cache_dir} {build_dir}" + // pip ignores '--global-option' when pep517 is enabled, we also enabling pip verbose to + // be reached from asv `--verbose` so we can verify the build options. + "PIP_NO_BUILD_ISOLATION=false python {build_dir}/benchmarks/asv_pip_nopep517.py -v {numpy_global_options} --no-deps --no-index -w {build_cache_dir} {build_dir}" ], // The commits after which the regression search in `asv publish` // should start looking for regressions. Dictionary whose keys are diff --git a/benchmarks/asv_pip_nopep517.py b/benchmarks/asv_pip_nopep517.py new file mode 100644 index 000000000..9ba165493 --- /dev/null +++ b/benchmarks/asv_pip_nopep517.py @@ -0,0 +1,15 @@ +""" +This file is used by asv_compare.conf.json.tpl. +""" +import subprocess, sys +# pip ignores '--global-option' when pep517 is enabled therefore we disable it. +cmd = [sys.executable, '-mpip', 'wheel', '--no-use-pep517'] +try: + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, universal_newlines=True) +except Exception as e: + output = str(e.output) +if "no such option" in output: + print("old version of pip, escape '--no-use-pep517'") + cmd.pop() + +subprocess.run(cmd + sys.argv[1:]) diff --git a/doc/neps/nep-0013-ufunc-overrides.rst b/doc/neps/nep-0013-ufunc-overrides.rst index 698e45738..4a647e9d3 100644 --- a/doc/neps/nep-0013-ufunc-overrides.rst +++ b/doc/neps/nep-0013-ufunc-overrides.rst @@ -46,8 +46,8 @@ right behaviour, hence the change in name.) The ``__array_ufunc__`` as described below requires that any corresponding Python binary operations (``__mul__`` et al.) should be -implemented in a specific way and be compatible with Numpy's ndarray -semantics. Objects that do not satisfy this cannot override any Numpy +implemented in a specific way and be compatible with NumPy's ndarray +semantics. Objects that do not satisfy this cannot override any NumPy ufuncs. We do not specify a future-compatible path by which this requirement can be relaxed --- any changes here require corresponding changes in 3rd party code. @@ -132,7 +132,7 @@ However, this behavior is more confusing than useful, and having a :exc:`TypeError` would be preferable. This proposal will *not* resolve the issue with scipy.sparse matrices, -which have multiplication semantics incompatible with numpy arrays. +which have multiplication semantics incompatible with NumPy arrays. However, the aim is to enable writing other custom array types that have strictly ndarray compatible semantics. @@ -246,7 +246,7 @@ three groups: - *Incompatible*: neither above nor below A; types for which no (indirect) upcasting is possible. -Note that the legacy behaviour of numpy ufuncs is to try to convert +Note that the legacy behaviour of NumPy ufuncs is to try to convert unknown objects to :class:`ndarray` via :func:`np.asarray`. This is equivalent to placing :class:`ndarray` above these objects in the graph. Since we above defined :class:`ndarray` to return `NotImplemented` for @@ -454,7 +454,7 @@ implements the following behavior: A class wishing to modify the interaction with :class:`ndarray` in binary operations therefore has two options: -1. Implement ``__array_ufunc__`` and follow Numpy semantics for Python +1. Implement ``__array_ufunc__`` and follow NumPy semantics for Python binary operations (see below). 2. Set ``__array_ufunc__ = None``, and implement Python binary @@ -678,7 +678,7 @@ NA ``abs`` :func:`absolute` Future extensions to other functions ------------------------------------ -Some numpy functions could be implemented as (generalized) Ufunc, in +Some NumPy functions could be implemented as (generalized) Ufunc, in which case it would be possible for them to be overridden by the ``__array_ufunc__`` method. A prime candidate is :func:`~numpy.matmul`, which currently is not a Ufunc, but could be relatively easily be diff --git a/doc/neps/nep-0023-backwards-compatibility.rst b/doc/neps/nep-0023-backwards-compatibility.rst index 158f46273..c8bd7c180 100644 --- a/doc/neps/nep-0023-backwards-compatibility.rst +++ b/doc/neps/nep-0023-backwards-compatibility.rst @@ -156,7 +156,7 @@ Removing complete submodules This year there have been suggestions to consider removing some or all of ``numpy.distutils``, ``numpy.f2py``, ``numpy.linalg``, and ``numpy.random``. The motivation was that all these cost maintenance effort, and that they slow -down work on the core of Numpy (ndarrays, dtypes and ufuncs). +down work on the core of NumPy (ndarrays, dtypes and ufuncs). The impact on downstream libraries and users would be very large, and maintenance of these modules would still have to happen. Therefore this is diff --git a/doc/neps/nep-0025-missing-data-3.rst b/doc/neps/nep-0025-missing-data-3.rst index ffe208c98..81045652e 100644 --- a/doc/neps/nep-0025-missing-data-3.rst +++ b/doc/neps/nep-0025-missing-data-3.rst @@ -62,7 +62,7 @@ values, (4) it is compatible with the common practice of using NaN to indicate missingness when working with floating point numbers, (5) the dtype is already a place where "weird things can happen" -- there are a wide variety of dtypes that don't act like ordinary numbers (including structs, Python objects, -fixed-length strings, ...), so code that accepts arbitrary numpy arrays already +fixed-length strings, ...), so code that accepts arbitrary NumPy arrays already has to be prepared to handle these (even if only by checking for them and raising an error). Therefore adding yet more new dtypes has less impact on extension authors than if we change the ndarray object itself. @@ -96,7 +96,7 @@ for consistency. General strategy ================ -Numpy already has a general mechanism for defining new dtypes and slotting them +NumPy already has a general mechanism for defining new dtypes and slotting them in so that they're supported by ndarrays, by the casting machinery, by ufuncs, and so on. In principle, we could implement NA-dtypes just using these existing interfaces. But we don't want to do that, because defining all those new ufunc @@ -271,7 +271,7 @@ below. Casting ------- -FIXME: this really needs attention from an expert on numpy's casting rules. But +FIXME: this really needs attention from an expert on NumPy's casting rules. But I can't seem to find the docs that explain how casting loops are looked up and decided between (e.g., if you're casting from dtype A to dtype B, which dtype's loops are used?), so I can't go into details. But those details are tricky and @@ -338,7 +338,7 @@ Printing -------- FIXME: There should be some sort of mechanism by which values which are NA are -automatically repr'ed as NA, but I don't really understand how numpy printing +automatically repr'ed as NA, but I don't really understand how NumPy printing works, so I'll let someone else fill in this section. Indexing @@ -364,10 +364,10 @@ own global singleton.) So for now we stick to scalar indexing just returning Python API for generic NA support ================================= -NumPy will gain a global singleton called numpy.NA, similar to None, but with +NumPy will gain a global singleton called ``numpy.NA``, similar to None, but with semantics reflecting its status as a missing value. In particular, trying to treat it as a boolean will raise an exception, and comparisons with it will -produce numpy.NA instead of True or False. These basics are adopted from the +produce ``numpy.NA`` instead of True or False. These basics are adopted from the behavior of the NA value in the R project. To dig deeper into the ideas, http://en.wikipedia.org/wiki/Ternary_logic#Kleene_logic provides a starting point. @@ -453,8 +453,8 @@ The NEP also contains a proposal for a somewhat elaborate domain-specific-language for describing NA dtypes. I'm not sure how great an idea that is. (I have a bias against using strings as data structures, and find the already existing strings confusing enough as it is -- also, apparently the -NEP version of numpy uses strings like 'f8' when printing dtypes, while my -numpy uses object names like 'float64', so I'm not sure what's going on there. +NEP version of NumPy uses strings like 'f8' when printing dtypes, while my +NumPy uses object names like 'float64', so I'm not sure what's going on there. ``withNA(float64, arg1=value1)`` seems like a more pleasant way to print a dtype than "NA[f8,value1]", at least to me.) But if people want it, then cool. diff --git a/doc/neps/nep-0027-zero-rank-arrarys.rst b/doc/neps/nep-0027-zero-rank-arrarys.rst index 2d152234c..cb3972675 100644 --- a/doc/neps/nep-0027-zero-rank-arrarys.rst +++ b/doc/neps/nep-0027-zero-rank-arrarys.rst @@ -57,7 +57,7 @@ However there are some important differences: Motivation for Array Scalars ---------------------------- -Numpy's design decision to provide 0-d arrays and array scalars in addition to +NumPy's design decision to provide 0-d arrays and array scalars in addition to native python types goes against one of the fundamental python design principles that there should be only one obvious way to do it. In this section we will try to explain why it is necessary to have three different ways to @@ -109,7 +109,7 @@ arrays to scalars were summarized as follows: are something like Python lists (which except for Object arrays they are not). -Numpy implements a solution that is designed to have all the pros and none of the cons above. +NumPy implements a solution that is designed to have all the pros and none of the cons above. Create Python scalar types for all of the 21 types and also inherit from the three that already exist. Define equivalent diff --git a/doc/neps/nep-0029-deprecation_policy.rst b/doc/neps/nep-0029-deprecation_policy.rst index 957674ee6..a50afcb98 100644 --- a/doc/neps/nep-0029-deprecation_policy.rst +++ b/doc/neps/nep-0029-deprecation_policy.rst @@ -1,7 +1,7 @@ .. _NEP29: ================================================================================== -NEP 29 — Recommend Python and Numpy version support as a community policy standard +NEP 29 — Recommend Python and NumPy version support as a community policy standard ================================================================================== @@ -124,14 +124,14 @@ Drop Schedule :: On next release, drop support for Python 3.5 (initially released on Sep 13, 2015) - On Jan 07, 2020 drop support for Numpy 1.14 (initially released on Jan 06, 2018) + On Jan 07, 2020 drop support for NumPy 1.14 (initially released on Jan 06, 2018) On Jun 23, 2020 drop support for Python 3.6 (initially released on Dec 23, 2016) - On Jul 23, 2020 drop support for Numpy 1.15 (initially released on Jul 23, 2018) - On Jan 13, 2021 drop support for Numpy 1.16 (initially released on Jan 13, 2019) - On Jul 26, 2021 drop support for Numpy 1.17 (initially released on Jul 26, 2019) - On Dec 22, 2021 drop support for Numpy 1.18 (initially released on Dec 22, 2019) + On Jul 23, 2020 drop support for NumPy 1.15 (initially released on Jul 23, 2018) + On Jan 13, 2021 drop support for NumPy 1.16 (initially released on Jan 13, 2019) + On Jul 26, 2021 drop support for NumPy 1.17 (initially released on Jul 26, 2019) + On Dec 22, 2021 drop support for NumPy 1.18 (initially released on Dec 22, 2019) On Dec 26, 2021 drop support for Python 3.7 (initially released on Jun 27, 2018) - On Jun 21, 2022 drop support for Numpy 1.19 (initially released on Jun 20, 2020) + On Jun 21, 2022 drop support for NumPy 1.19 (initially released on Jun 20, 2020) On Apr 14, 2023 drop support for Python 3.8 (initially released on Oct 14, 2019) @@ -249,18 +249,18 @@ Code to generate support and drop schedule tables :: from datetime import datetime, timedelta - data = """Jan 15, 2017: Numpy 1.12 + data = """Jan 15, 2017: NumPy 1.12 Sep 13, 2015: Python 3.5 Dec 23, 2016: Python 3.6 Jun 27, 2018: Python 3.7 - Jun 07, 2017: Numpy 1.13 - Jan 06, 2018: Numpy 1.14 - Jul 23, 2018: Numpy 1.15 - Jan 13, 2019: Numpy 1.16 - Jul 26, 2019: Numpy 1.17 + Jun 07, 2017: NumPy 1.13 + Jan 06, 2018: NumPy 1.14 + Jul 23, 2018: NumPy 1.15 + Jan 13, 2019: NumPy 1.16 + Jul 26, 2019: NumPy 1.17 Oct 14, 2019: Python 3.8 - Dec 22, 2019: Numpy 1.18 - Jun 20, 2020: Numpy 1.19 + Dec 22, 2019: NumPy 1.18 + Jun 20, 2020: NumPy 1.19 """ releases = [] @@ -284,7 +284,7 @@ Code to generate support and drop schedule tables :: py_major,py_minor = sorted([int(x) for x in r[2].split('.')] for r in releases if r[1] == 'Python')[-1] minpy = f"{py_major}.{py_minor+1}+" - num_major,num_minor = sorted([int(x) for x in r[2].split('.')] for r in releases if r[1] == 'Numpy')[-1] + num_major,num_minor = sorted([int(x) for x in r[2].split('.')] for r in releases if r[1] == 'NumPy')[-1] minnum = f"{num_major}.{num_minor+1}+" toprint_drop_dates = [''] diff --git a/doc/neps/nep-0032-remove-financial-functions.rst b/doc/neps/nep-0032-remove-financial-functions.rst index 1c3722f46..bf98a7467 100644 --- a/doc/neps/nep-0032-remove-financial-functions.rst +++ b/doc/neps/nep-0032-remove-financial-functions.rst @@ -174,19 +174,19 @@ References and footnotes .. [1] Financial functions, https://numpy.org/doc/1.17/reference/routines.financial.html -.. [2] Numpy-discussion mailing list, "Simple financial functions for NumPy", +.. [2] NumPy-Discussion mailing list, "Simple financial functions for NumPy", https://mail.python.org/pipermail/numpy-discussion/2008-April/032353.html -.. [3] Numpy-discussion mailing list, "add xirr to numpy financial functions?", +.. [3] NumPy-Discussion mailing list, "add xirr to numpy financial functions?", https://mail.python.org/pipermail/numpy-discussion/2009-May/042645.html -.. [4] Numpy-discussion mailing list, "Definitions of pv, fv, nper, pmt, and rate", +.. [4] NumPy-Discussion mailing list, "Definitions of pv, fv, nper, pmt, and rate", https://mail.python.org/pipermail/numpy-discussion/2009-June/043188.html .. [5] Get financial functions out of main namespace, https://github.com/numpy/numpy/issues/2880 -.. [6] Numpy-discussion mailing list, "Deprecation of financial routines", +.. [6] NumPy-Discussion mailing list, "Deprecation of financial routines", https://mail.python.org/pipermail/numpy-discussion/2013-August/067409.html .. [7] ``component: numpy.lib.financial`` issues, @@ -198,7 +198,7 @@ References and footnotes .. [9] Quansight-Labs/python-api-inspect, https://github.com/Quansight-Labs/python-api-inspect/ -.. [10] Numpy-discussion mailing list, "NEP 32: Remove the financial functions +.. [10] NumPy-Discussion mailing list, "NEP 32: Remove the financial functions from NumPy" https://mail.python.org/pipermail/numpy-discussion/2019-September/079965.html @@ -206,7 +206,7 @@ References and footnotes remove the financial functions. https://mail.google.com/mail/u/0/h/1w0mjgixc4rpe/?&th=16d5c38be45f77c4&q=nep+32&v=c&s=q -.. [12] Numpy-discussion mailing list, "Proposal to accept NEP 32: Remove the +.. [12] NumPy-Discussion mailing list, "Proposal to accept NEP 32: Remove the financial functions from NumPy" https://mail.python.org/pipermail/numpy-discussion/2019-September/080074.html diff --git a/doc/neps/nep-0042-new-dtypes.rst b/doc/neps/nep-0042-new-dtypes.rst index 1a77b5718..1738bd1ab 100644 --- a/doc/neps/nep-0042-new-dtypes.rst +++ b/doc/neps/nep-0042-new-dtypes.rst @@ -8,10 +8,10 @@ NEP 42 — New and extensible DTypes :Author: Sebastian Berg :Author: Ben Nathanson :Author: Marten van Kerkwijk -:Status: Draft +:Status: Accepted :Type: Standard :Created: 2019-07-17 - +:Resolution: https://mail.python.org/pipermail/numpy-discussion/2020-October/081038.html .. note:: diff --git a/doc/release/upcoming_changes/17921.compatibility.rst b/doc/release/upcoming_changes/17921.compatibility.rst new file mode 100644 index 000000000..a1e2fb2d0 --- /dev/null +++ b/doc/release/upcoming_changes/17921.compatibility.rst @@ -0,0 +1,6 @@ +Validate input values in ``Generator.uniform`` +---------------------------------------------- +Checked that ``high - low >= 0`` in ``np.random.Generator.uniform``. Raises +``ValueError`` if ``low > high``. Previously out-of-order inputs were accepted +and silently swapped, so that if ``low > high``, the value generated was +``high + (low - high) * random()``. diff --git a/doc/source/_templates/autosummary/module.rst b/doc/source/_templates/autosummary/module.rst new file mode 100644 index 000000000..e1f428d65 --- /dev/null +++ b/doc/source/_templates/autosummary/module.rst @@ -0,0 +1,40 @@ +{% extends "!autosummary/module.rst" %} + +{# This file is almost the same as the default, but adds :toctree: to the autosummary directives. + The original can be found at `sphinx/ext/autosummary/templates/autosummary/module.rst`. #} + +{% block attributes %} +{% if attributes %} + .. rubric:: Module Attributes + + .. autosummary:: + :toctree: + {% for item in attributes %} + {{ item }} + {%- endfor %} +{% endif %} +{% endblock %} + +{% block functions %} +{% if functions %} + .. rubric:: Functions + + .. autosummary:: + :toctree: + {% for item in functions %} + {{ item }} + {%- endfor %} +{% endif %} +{% endblock %} + +{% block classes %} +{% if classes %} + .. rubric:: Classes + + .. autosummary:: + :toctree: + {% for item in classes %} + {{ item }} + {%- endfor %} +{% endif %} +{% endblock %} diff --git a/doc/source/conf.py b/doc/source/conf.py index 381a01612..e76f60063 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -4,7 +4,7 @@ import re import sys # Minimum version, enforced by sphinx -needs_sphinx = '2.2.0' +needs_sphinx = '3.2.0' # This is a nasty hack to use platform-agnostic names for types in the @@ -146,6 +146,14 @@ def setup(app): app.add_config_value('python_version_major', str(sys.version_info.major), 'env') app.add_lexer('NumPyC', NumPyLexer) +# While these objects do have type `module`, the names are aliases for modules +# elsewhere. Sphinx does not support referring to modules by an aliases name, +# so we make the alias look like a "real" module for it. +# If we deemed it desirable, we could in future make these real modules, which +# would make `from numpy.char import split` work. +sys.modules['numpy.char'] = numpy.char +sys.modules['numpy.testing.dec'] = numpy.testing.dec + # ----------------------------------------------------------------------------- # HTML output # ----------------------------------------------------------------------------- diff --git a/doc/source/reference/arrays.scalars.rst b/doc/source/reference/arrays.scalars.rst index 4b5da2e13..29438f70f 100644 --- a/doc/source/reference/arrays.scalars.rst +++ b/doc/source/reference/arrays.scalars.rst @@ -94,112 +94,141 @@ Python Boolean scalar. .. tip:: The default data type in NumPy is :class:`float_`. .. autoclass:: numpy.generic - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.number - :exclude-members: + :members: __init__ + :exclude-members: __init__ Integer types ~~~~~~~~~~~~~ .. autoclass:: numpy.integer - :exclude-members: + :members: __init__ + :exclude-members: __init__ Signed integer types ++++++++++++++++++++ .. autoclass:: numpy.signedinteger - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.byte - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.short - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.intc - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.int_ - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.longlong - :exclude-members: + :members: __init__ + :exclude-members: __init__ Unsigned integer types ++++++++++++++++++++++ .. autoclass:: numpy.unsignedinteger - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.ubyte - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.ushort - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.uintc - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.uint - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.ulonglong - :exclude-members: + :members: __init__ + :exclude-members: __init__ Inexact types ~~~~~~~~~~~~~ .. autoclass:: numpy.inexact - :exclude-members: + :members: __init__ + :exclude-members: __init__ Floating-point types ++++++++++++++++++++ .. autoclass:: numpy.floating - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.half - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.single - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.double - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.longdouble - :exclude-members: + :members: __init__ + :exclude-members: __init__ Complex floating-point types ++++++++++++++++++++++++++++ .. autoclass:: numpy.complexfloating - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.csingle - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.cdouble - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.clongdouble - :exclude-members: + :members: __init__ + :exclude-members: __init__ Other types ~~~~~~~~~~~ .. autoclass:: numpy.bool_ - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.datetime64 - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.timedelta64 - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.object_ - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. note:: @@ -222,16 +251,20 @@ arrays. (In the character codes ``#`` is an integer denoting how many elements the data type consists of.) .. autoclass:: numpy.flexible - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.bytes_ - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.str_ - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. autoclass:: numpy.void - :exclude-members: + :members: __init__ + :exclude-members: __init__ .. warning:: diff --git a/doc/source/reference/c-api/array.rst b/doc/source/reference/c-api/array.rst index 3aa541b79..1673f1d6b 100644 --- a/doc/source/reference/c-api/array.rst +++ b/doc/source/reference/c-api/array.rst @@ -22,8 +22,8 @@ Array structure and data access These macros access the :c:type:`PyArrayObject` structure members and are defined in ``ndarraytypes.h``. The input argument, *arr*, can be any -:c:type:`PyObject *<PyObject>` that is directly interpretable as a -:c:type:`PyArrayObject *` (any instance of the :c:data:`PyArray_Type` +:c:expr:`PyObject *` that is directly interpretable as a +:c:expr:`PyArrayObject *` (any instance of the :c:data:`PyArray_Type` and its sub-types). .. c:function:: int PyArray_NDIM(PyArrayObject *arr) @@ -825,7 +825,7 @@ General check of Python Type Evaluates true if *op* is an instance of (a subclass of) :c:data:`PyArray_Type` and has 0 dimensions. -.. c:function:: PyArray_IsScalar(op, cls) +.. c:macro:: PyArray_IsScalar(op, cls) Evaluates true if *op* is an instance of ``Py{cls}ArrType_Type``. @@ -864,8 +864,8 @@ Data-type checking For the typenum macros, the argument is an integer representing an enumerated array data type. For the array type checking macros the -argument must be a :c:type:`PyObject *<PyObject>` that can be directly interpreted as a -:c:type:`PyArrayObject *`. +argument must be a :c:expr:`PyObject *` that can be directly interpreted as a +:c:expr:`PyArrayObject *`. .. c:function:: int PyTypeNum_ISUNSIGNED(int num) @@ -1022,7 +1022,7 @@ argument must be a :c:type:`PyObject *<PyObject>` that can be directly interpret .. c:function:: int PyArray_EquivByteorders(int b1, int b2) - True if byteorder characters ( :c:data:`NPY_LITTLE`, + True if byteorder characters *b1* and *b2* ( :c:data:`NPY_LITTLE`, :c:data:`NPY_BIG`, :c:data:`NPY_NATIVE`, :c:data:`NPY_IGNORE` ) are either equal or equivalent as to their specification of a native byte order. Thus, on a little-endian machine :c:data:`NPY_LITTLE` @@ -2781,14 +2781,14 @@ Data-type descriptors Data-type objects must be reference counted so be aware of the action on the data-type reference of different C-API calls. The standard rule is that when a data-type object is returned it is a - new reference. Functions that take :c:type:`PyArray_Descr *` objects and + new reference. Functions that take :c:expr:`PyArray_Descr *` objects and return arrays steal references to the data-type their inputs unless otherwise noted. Therefore, you must own a reference to any data-type object used as input to such a function. .. c:function:: int PyArray_DescrCheck(PyObject* obj) - Evaluates as true if *obj* is a data-type object ( :c:type:`PyArray_Descr *` ). + Evaluates as true if *obj* is a data-type object ( :c:expr:`PyArray_Descr *` ). .. c:function:: PyArray_Descr* PyArray_DescrNew(PyArray_Descr* obj) @@ -3485,10 +3485,6 @@ Miscellaneous Macros Evaluates as True if arrays *a1* and *a2* have the same shape. -.. c:var:: a - -.. c:var:: b - .. c:macro:: PyArray_MAX(a,b) Returns the maximum of *a* and *b*. If (*a*) or (*b*) are @@ -3547,22 +3543,22 @@ Miscellaneous Macros Enumerated Types ^^^^^^^^^^^^^^^^ -.. c:type:: NPY_SORTKIND +.. c:enum:: NPY_SORTKIND A special variable-type which can take on different values to indicate the sorting algorithm being used. - .. c:var:: NPY_QUICKSORT + .. c:enumerator:: NPY_QUICKSORT - .. c:var:: NPY_HEAPSORT + .. c:enumerator:: NPY_HEAPSORT - .. c:var:: NPY_MERGESORT + .. c:enumerator:: NPY_MERGESORT - .. c:var:: NPY_STABLESORT + .. c:enumerator:: NPY_STABLESORT Used as an alias of :c:data:`NPY_MERGESORT` and vica versa. - .. c:var:: NPY_NSORTS + .. c:enumerator:: NPY_NSORTS Defined to be the number of sorts. It is fixed at three by the need for backwards compatibility, and consequently :c:data:`NPY_MERGESORT` and @@ -3570,90 +3566,90 @@ Enumerated Types of several stable sorting algorithms depending on the data type. -.. c:type:: NPY_SCALARKIND +.. c:enum:: NPY_SCALARKIND A special variable type indicating the number of "kinds" of scalars distinguished in determining scalar-coercion rules. This variable can take on the values: - .. c:var:: NPY_NOSCALAR + .. c:enumerator:: NPY_NOSCALAR - .. c:var:: NPY_BOOL_SCALAR + .. c:enumerator:: NPY_BOOL_SCALAR - .. c:var:: NPY_INTPOS_SCALAR + .. c:enumerator:: NPY_INTPOS_SCALAR - .. c:var:: NPY_INTNEG_SCALAR + .. c:enumerator:: NPY_INTNEG_SCALAR - .. c:var:: NPY_FLOAT_SCALAR + .. c:enumerator:: NPY_FLOAT_SCALAR - .. c:var:: NPY_COMPLEX_SCALAR + .. c:enumerator:: NPY_COMPLEX_SCALAR - .. c:var:: NPY_OBJECT_SCALAR + .. c:enumerator:: NPY_OBJECT_SCALAR - .. c:var:: NPY_NSCALARKINDS + .. c:enumerator:: NPY_NSCALARKINDS Defined to be the number of scalar kinds (not including :c:data:`NPY_NOSCALAR`). -.. c:type:: NPY_ORDER +.. c:enum:: NPY_ORDER An enumeration type indicating the element order that an array should be interpreted in. When a brand new array is created, generally only **NPY_CORDER** and **NPY_FORTRANORDER** are used, whereas when one or more inputs are provided, the order can be based on them. - .. c:var:: NPY_ANYORDER + .. c:enumerator:: NPY_ANYORDER Fortran order if all the inputs are Fortran, C otherwise. - .. c:var:: NPY_CORDER + .. c:enumerator:: NPY_CORDER C order. - .. c:var:: NPY_FORTRANORDER + .. c:enumerator:: NPY_FORTRANORDER Fortran order. - .. c:var:: NPY_KEEPORDER + .. c:enumerator:: NPY_KEEPORDER An order as close to the order of the inputs as possible, even if the input is in neither C nor Fortran order. -.. c:type:: NPY_CLIPMODE +.. c:enum:: NPY_CLIPMODE A variable type indicating the kind of clipping that should be applied in certain functions. - .. c:var:: NPY_RAISE + .. c:enumerator:: NPY_RAISE The default for most operations, raises an exception if an index is out of bounds. - .. c:var:: NPY_CLIP + .. c:enumerator:: NPY_CLIP Clips an index to the valid range if it is out of bounds. - .. c:var:: NPY_WRAP + .. c:enumerator:: NPY_WRAP Wraps an index to the valid range if it is out of bounds. -.. c:type:: NPY_SEARCHSIDE +.. c:enum:: NPY_SEARCHSIDE A variable type indicating whether the index returned should be that of the first suitable location (if :c:data:`NPY_SEARCHLEFT`) or of the last (if :c:data:`NPY_SEARCHRIGHT`). - .. c:var:: NPY_SEARCHLEFT + .. c:enumerator:: NPY_SEARCHLEFT - .. c:var:: NPY_SEARCHRIGHT + .. c:enumerator:: NPY_SEARCHRIGHT -.. c:type:: NPY_SELECTKIND +.. c:enum:: NPY_SELECTKIND A variable type indicating the selection algorithm being used. - .. c:var:: NPY_INTROSELECT + .. c:enumerator:: NPY_INTROSELECT -.. c:type:: NPY_CASTING +.. c:enum:: NPY_CASTING .. versionadded:: 1.6 @@ -3661,25 +3657,25 @@ Enumerated Types be. This is used by the iterator added in NumPy 1.6, and is intended to be used more broadly in a future version. - .. c:var:: NPY_NO_CASTING + .. c:enumerator:: NPY_NO_CASTING Only allow identical types. - .. c:var:: NPY_EQUIV_CASTING + .. c:enumerator:: NPY_EQUIV_CASTING Allow identical and casts involving byte swapping. - .. c:var:: NPY_SAFE_CASTING + .. c:enumerator:: NPY_SAFE_CASTING Only allow casts which will not cause values to be rounded, truncated, or otherwise changed. - .. c:var:: NPY_SAME_KIND_CASTING + .. c:enumerator:: NPY_SAME_KIND_CASTING Allow any safe casts, and casts between types of the same kind. For example, float64 -> float32 is permitted with this rule. - .. c:var:: NPY_UNSAFE_CASTING + .. c:enumerator:: NPY_UNSAFE_CASTING Allow any cast, no matter what kind of data loss may occur. diff --git a/doc/source/reference/c-api/coremath.rst b/doc/source/reference/c-api/coremath.rst index 338c584a1..cec83b150 100644 --- a/doc/source/reference/c-api/coremath.rst +++ b/doc/source/reference/c-api/coremath.rst @@ -46,30 +46,30 @@ Floating point classification corresponding single and extension precision macro are available with the suffix F and L. -.. c:function:: int npy_isnan(x) +.. c:macro:: npy_isnan(x) This is a macro, and is equivalent to C99 isnan: works for single, double and extended precision, and return a non 0 value is x is a NaN. -.. c:function:: int npy_isfinite(x) +.. c:macro:: npy_isfinite(x) This is a macro, and is equivalent to C99 isfinite: works for single, double and extended precision, and return a non 0 value is x is neither a NaN nor an infinity. -.. c:function:: int npy_isinf(x) +.. c:macro:: npy_isinf(x) This is a macro, and is equivalent to C99 isinf: works for single, double and extended precision, and return a non 0 value is x is infinite (positive and negative). -.. c:function:: int npy_signbit(x) +.. c:macro:: npy_signbit(x) This is a macro, and is equivalent to C99 signbit: works for single, double and extended precision, and return a non 0 value is x has the signbit set (that is the number is negative). -.. c:function:: double npy_copysign(double x, double y) +.. c:macro:: npy_copysign(x, y) This is a function equivalent to C99 copysign: return x with the same sign as y. Works for any value, including inf and nan. Single and extended diff --git a/doc/source/reference/c-api/dtype.rst b/doc/source/reference/c-api/dtype.rst index a1a53cdb6..382e45dc0 100644 --- a/doc/source/reference/c-api/dtype.rst +++ b/doc/source/reference/c-api/dtype.rst @@ -25,157 +25,157 @@ select the precision desired. Enumerated Types ---------------- -.. c:var:: NPY_TYPES +.. c:enumerator:: NPY_TYPES There is a list of enumerated types defined providing the basic 24 data types plus some useful generic names. Whenever the code requires a type number, one of these enumerated types is requested. The types are all called ``NPY_{NAME}``: -.. c:var:: NPY_BOOL +.. c:enumerator:: NPY_BOOL The enumeration value for the boolean type, stored as one byte. It may only be set to the values 0 and 1. -.. c:var:: NPY_BYTE -.. c:var:: NPY_INT8 +.. c:enumerator:: NPY_BYTE +.. c:enumerator:: NPY_INT8 The enumeration value for an 8-bit/1-byte signed integer. -.. c:var:: NPY_SHORT -.. c:var:: NPY_INT16 +.. c:enumerator:: NPY_SHORT +.. c:enumerator:: NPY_INT16 The enumeration value for a 16-bit/2-byte signed integer. -.. c:var:: NPY_INT -.. c:var:: NPY_INT32 +.. c:enumerator:: NPY_INT +.. c:enumerator:: NPY_INT32 The enumeration value for a 32-bit/4-byte signed integer. -.. c:var:: NPY_LONG +.. c:enumerator:: NPY_LONG Equivalent to either NPY_INT or NPY_LONGLONG, depending on the platform. -.. c:var:: NPY_LONGLONG -.. c:var:: NPY_INT64 +.. c:enumerator:: NPY_LONGLONG +.. c:enumerator:: NPY_INT64 The enumeration value for a 64-bit/8-byte signed integer. -.. c:var:: NPY_UBYTE -.. c:var:: NPY_UINT8 +.. c:enumerator:: NPY_UBYTE +.. c:enumerator:: NPY_UINT8 The enumeration value for an 8-bit/1-byte unsigned integer. -.. c:var:: NPY_USHORT -.. c:var:: NPY_UINT16 +.. c:enumerator:: NPY_USHORT +.. c:enumerator:: NPY_UINT16 The enumeration value for a 16-bit/2-byte unsigned integer. -.. c:var:: NPY_UINT -.. c:var:: NPY_UINT32 +.. c:enumerator:: NPY_UINT +.. c:enumerator:: NPY_UINT32 The enumeration value for a 32-bit/4-byte unsigned integer. -.. c:var:: NPY_ULONG +.. c:enumerator:: NPY_ULONG Equivalent to either NPY_UINT or NPY_ULONGLONG, depending on the platform. -.. c:var:: NPY_ULONGLONG -.. c:var:: NPY_UINT64 +.. c:enumerator:: NPY_ULONGLONG +.. c:enumerator:: NPY_UINT64 The enumeration value for a 64-bit/8-byte unsigned integer. -.. c:var:: NPY_HALF -.. c:var:: NPY_FLOAT16 +.. c:enumerator:: NPY_HALF +.. c:enumerator:: NPY_FLOAT16 The enumeration value for a 16-bit/2-byte IEEE 754-2008 compatible floating point type. -.. c:var:: NPY_FLOAT -.. c:var:: NPY_FLOAT32 +.. c:enumerator:: NPY_FLOAT +.. c:enumerator:: NPY_FLOAT32 The enumeration value for a 32-bit/4-byte IEEE 754 compatible floating point type. -.. c:var:: NPY_DOUBLE -.. c:var:: NPY_FLOAT64 +.. c:enumerator:: NPY_DOUBLE +.. c:enumerator:: NPY_FLOAT64 The enumeration value for a 64-bit/8-byte IEEE 754 compatible floating point type. -.. c:var:: NPY_LONGDOUBLE +.. c:enumerator:: NPY_LONGDOUBLE The enumeration value for a platform-specific floating point type which is at least as large as NPY_DOUBLE, but larger on many platforms. -.. c:var:: NPY_CFLOAT -.. c:var:: NPY_COMPLEX64 +.. c:enumerator:: NPY_CFLOAT +.. c:enumerator:: NPY_COMPLEX64 The enumeration value for a 64-bit/8-byte complex type made up of two NPY_FLOAT values. -.. c:var:: NPY_CDOUBLE -.. c:var:: NPY_COMPLEX128 +.. c:enumerator:: NPY_CDOUBLE +.. c:enumerator:: NPY_COMPLEX128 The enumeration value for a 128-bit/16-byte complex type made up of two NPY_DOUBLE values. -.. c:var:: NPY_CLONGDOUBLE +.. c:enumerator:: NPY_CLONGDOUBLE The enumeration value for a platform-specific complex floating point type which is made up of two NPY_LONGDOUBLE values. -.. c:var:: NPY_DATETIME +.. c:enumerator:: NPY_DATETIME The enumeration value for a data type which holds dates or datetimes with a precision based on selectable date or time units. -.. c:var:: NPY_TIMEDELTA +.. c:enumerator:: NPY_TIMEDELTA The enumeration value for a data type which holds lengths of times in integers of selectable date or time units. -.. c:var:: NPY_STRING +.. c:enumerator:: NPY_STRING The enumeration value for ASCII strings of a selectable size. The strings have a fixed maximum size within a given array. -.. c:var:: NPY_UNICODE +.. c:enumerator:: NPY_UNICODE The enumeration value for UCS4 strings of a selectable size. The strings have a fixed maximum size within a given array. -.. c:var:: NPY_OBJECT +.. c:enumerator:: NPY_OBJECT The enumeration value for references to arbitrary Python objects. -.. c:var:: NPY_VOID +.. c:enumerator:: NPY_VOID Primarily used to hold struct dtypes, but can contain arbitrary binary data. Some useful aliases of the above types are -.. c:var:: NPY_INTP +.. c:enumerator:: NPY_INTP The enumeration value for a signed integer type which is the same size as a (void \*) pointer. This is the type used by all arrays of indices. -.. c:var:: NPY_UINTP +.. c:enumerator:: NPY_UINTP The enumeration value for an unsigned integer type which is the same size as a (void \*) pointer. -.. c:var:: NPY_MASK +.. c:enumerator:: NPY_MASK The enumeration value of the type used for masks, such as with the :c:data:`NPY_ITER_ARRAYMASK` iterator flag. This is equivalent to :c:data:`NPY_UINT8`. -.. c:var:: NPY_DEFAULT_TYPE +.. c:enumerator:: NPY_DEFAULT_TYPE The default type to use when no dtype is explicitly specified, for example when calling np.zero(shape). This is equivalent to @@ -297,9 +297,13 @@ Boolean Unsigned versions of the integers can be defined by pre-pending a 'u' to the front of the integer name. -.. c:type:: npy_(u)byte +.. c:type:: npy_byte - (unsigned) char + char + +.. c:type:: npy_ubyte + + unsigned char .. c:type:: npy_short @@ -309,14 +313,14 @@ to the front of the integer name. unsigned short -.. c:type:: npy_uint - - unsigned int - .. c:type:: npy_int int +.. c:type:: npy_uint + + unsigned int + .. c:type:: npy_int16 16-bit integer @@ -341,13 +345,21 @@ to the front of the integer name. 64-bit unsigned integer -.. c:type:: npy_(u)long +.. c:type:: npy_long - (unsigned) long int + long int -.. c:type:: npy_(u)longlong +.. c:type:: npy_ulong - (unsigned long long int) + unsigned long int + +.. c:type:: npy_longlong + + long long int + +.. c:type:: npy_ulonglong + + unsigned long long int .. c:type:: npy_intp @@ -367,18 +379,30 @@ to the front of the integer name. 16-bit float -.. c:type:: npy_(c)float +.. c:type:: npy_float 32-bit float -.. c:type:: npy_(c)double +.. c:type:: npy_cfloat + + 32-bit complex float + +.. c:type:: npy_double 64-bit double -.. c:type:: npy_(c)longdouble +.. c:type:: npy_cdouble + + 64-bit complex double + +.. c:type:: npy_longdouble long double +.. c:type:: npy_clongdouble + + long complex double + complex types are structures with **.real** and **.imag** members (in that order). diff --git a/doc/source/reference/c-api/iterator.rst b/doc/source/reference/c-api/iterator.rst index ae96bb3fb..add96e3b4 100644 --- a/doc/source/reference/c-api/iterator.rst +++ b/doc/source/reference/c-api/iterator.rst @@ -370,7 +370,7 @@ Construction and Destruction arrays or structured arrays containing an object type) may be accepted and used in the iterator. If this flag is enabled, the caller must be sure to check whether - :c:func:`NpyIter_IterationNeedsAPI(iter)` is true, in which case + :c:expr:`NpyIter_IterationNeedsAPI(iter)` is true, in which case it may not release the GIL during iteration. .. c:macro:: NPY_ITER_ZEROSIZE_OK @@ -738,7 +738,7 @@ Construction and Destruction the iterator. Any cached functions or pointers from the iterator must be retrieved again! - After calling this function, :c:func:`NpyIter_HasMultiIndex(iter)` will + After calling this function, :c:expr:`NpyIter_HasMultiIndex(iter)` will return false. Returns ``NPY_SUCCEED`` or ``NPY_FAIL``. diff --git a/doc/source/reference/c-api/types-and-structures.rst b/doc/source/reference/c-api/types-and-structures.rst index 763f985a6..ab82fda87 100644 --- a/doc/source/reference/c-api/types-and-structures.rst +++ b/doc/source/reference/c-api/types-and-structures.rst @@ -7,7 +7,7 @@ Python Types and C-Structures Several new types are defined in the C-code. Most of these are accessible from Python, but a few are not exposed due to their limited -use. Every new Python type has an associated :c:type:`PyObject *<PyObject>` with an +use. Every new Python type has an associated :c:expr:`PyObject *` with an internal structure that includes a pointer to a "method table" that defines how the new object behaves in Python. When you receive a Python object into C code, you always get a pointer to a @@ -61,7 +61,7 @@ hierarchy of actual Python types. PyArray_Type and PyArrayObject ------------------------------ -.. c:var:: PyArray_Type +.. c:var:: PyTypeObject PyArray_Type The Python type of the ndarray is :c:data:`PyArray_Type`. In C, every ndarray is a pointer to a :c:type:`PyArrayObject` structure. The ob_type @@ -201,7 +201,7 @@ PyArray_Type and PyArrayObject PyArrayDescr_Type and PyArray_Descr ----------------------------------- -.. c:var:: PyArrayDescr_Type +.. c:var:: PyTypeObject PyArrayDescr_Type The :c:data:`PyArrayDescr_Type` is the built-in type of the data-type-descriptor objects used to describe how the bytes comprising @@ -636,7 +636,7 @@ PyArrayDescr_Type and PyArray_Descr Either ``NULL`` or a dictionary containing low-level casting functions for user- defined data-types. Each function is - wrapped in a :c:type:`PyCapsule *<PyCapsule>` and keyed by + wrapped in a :c:expr:`PyCapsule *` and keyed by the data-type number. .. c:member:: NPY_SCALARKIND scalarkind(PyArrayObject* arr) @@ -754,7 +754,7 @@ The :c:data:`PyArray_Type` can also be sub-typed. PyUFunc_Type and PyUFuncObject ------------------------------ -.. c:var:: PyUFunc_Type +.. c:var:: PyTypeObject PyUFunc_Type The ufunc object is implemented by creation of the :c:data:`PyUFunc_Type`. It is a very simple type that implements only @@ -1006,7 +1006,7 @@ PyUFunc_Type and PyUFuncObject PyArrayIter_Type and PyArrayIterObject -------------------------------------- -.. c:var:: PyArrayIter_Type +.. c:var:: PyTypeObject PyArrayIter_Type This is an iterator object that makes it easy to loop over an N-dimensional array. It is the object returned from the flat @@ -1110,13 +1110,13 @@ the internal structure of the iterator object, and merely interact with it through the use of the macros :c:func:`PyArray_ITER_NEXT` (it), :c:func:`PyArray_ITER_GOTO` (it, dest), or :c:func:`PyArray_ITER_GOTO1D` (it, index). All of these macros require the argument *it* to be a -:c:type:`PyArrayIterObject *`. +:c:expr:`PyArrayIterObject *`. PyArrayMultiIter_Type and PyArrayMultiIterObject ------------------------------------------------ -.. c:var:: PyArrayMultiIter_Type +.. c:var:: PyTypeObject PyArrayMultiIter_Type This type provides an iterator that encapsulates the concept of broadcasting. It allows :math:`N` arrays to be broadcast together @@ -1178,7 +1178,7 @@ PyArrayMultiIter_Type and PyArrayMultiIterObject PyArrayNeighborhoodIter_Type and PyArrayNeighborhoodIterObject -------------------------------------------------------------- -.. c:var:: PyArrayNeighborhoodIter_Type +.. c:var:: PyTypeObject PyArrayNeighborhoodIter_Type This is an iterator object that makes it easy to loop over an N-dimensional neighborhood. @@ -1217,7 +1217,7 @@ PyArrayNeighborhoodIter_Type and PyArrayNeighborhoodIterObject PyArrayFlags_Type and PyArrayFlagsObject ---------------------------------------- -.. c:var:: PyArrayFlags_Type +.. c:var:: PyTypeObject PyArrayFlags_Type When the flags attribute is retrieved from Python, a special builtin object of this type is constructed. This special type makes @@ -1466,7 +1466,7 @@ for completeness and assistance in understanding the code. to define a 1-d loop for a ufunc for every defined signature of a user-defined data-type. -.. c:var:: PyArrayMapIter_Type +.. c:var:: PyTypeObject PyArrayMapIter_Type Advanced indexing is handled with this Python type. It is simply a loose wrapper around the C-structure containing the variables diff --git a/doc/source/reference/random/bit_generators/mt19937.rst b/doc/source/reference/random/bit_generators/mt19937.rst index 71875db4e..d05ea7c6f 100644 --- a/doc/source/reference/random/bit_generators/mt19937.rst +++ b/doc/source/reference/random/bit_generators/mt19937.rst @@ -4,7 +4,8 @@ Mersenne Twister (MT19937) .. currentmodule:: numpy.random .. autoclass:: MT19937 - :exclude-members: + :members: __init__ + :exclude-members: __init__ State ===== diff --git a/doc/source/reference/random/bit_generators/pcg64.rst b/doc/source/reference/random/bit_generators/pcg64.rst index edac4620b..889965f77 100644 --- a/doc/source/reference/random/bit_generators/pcg64.rst +++ b/doc/source/reference/random/bit_generators/pcg64.rst @@ -4,7 +4,8 @@ Permuted Congruential Generator (64-bit, PCG64) .. currentmodule:: numpy.random .. autoclass:: PCG64 - :exclude-members: + :members: __init__ + :exclude-members: __init__ State ===== diff --git a/doc/source/reference/random/bit_generators/philox.rst b/doc/source/reference/random/bit_generators/philox.rst index 8eba2d351..3c2fa4cc5 100644 --- a/doc/source/reference/random/bit_generators/philox.rst +++ b/doc/source/reference/random/bit_generators/philox.rst @@ -4,7 +4,8 @@ Philox Counter-based RNG .. currentmodule:: numpy.random .. autoclass:: Philox - :exclude-members: + :members: __init__ + :exclude-members: __init__ State ===== diff --git a/doc/source/reference/random/bit_generators/sfc64.rst b/doc/source/reference/random/bit_generators/sfc64.rst index d34124a33..8cb255bc1 100644 --- a/doc/source/reference/random/bit_generators/sfc64.rst +++ b/doc/source/reference/random/bit_generators/sfc64.rst @@ -4,7 +4,8 @@ SFC64 Small Fast Chaotic PRNG .. currentmodule:: numpy.random .. autoclass:: SFC64 - :exclude-members: + :members: __init__ + :exclude-members: __init__ State ===== diff --git a/doc/source/reference/random/generator.rst b/doc/source/reference/random/generator.rst index 8706e1de2..a359d2253 100644 --- a/doc/source/reference/random/generator.rst +++ b/doc/source/reference/random/generator.rst @@ -15,7 +15,8 @@ can be changed by passing an instantized BitGenerator to ``Generator``. .. autofunction:: default_rng .. autoclass:: Generator - :exclude-members: + :members: __init__ + :exclude-members: __init__ Accessing the BitGenerator ========================== diff --git a/doc/source/reference/random/legacy.rst b/doc/source/reference/random/legacy.rst index 6cf4775b8..42437dbb6 100644 --- a/doc/source/reference/random/legacy.rst +++ b/doc/source/reference/random/legacy.rst @@ -48,7 +48,8 @@ using the state of the `RandomState`: .. autoclass:: RandomState - :exclude-members: + :members: __init__ + :exclude-members: __init__ Seeding and State ================= diff --git a/doc/source/reference/routines.polynomials.rst b/doc/source/reference/routines.polynomials.rst index e74c5a683..da481ae4c 100644 --- a/doc/source/reference/routines.polynomials.rst +++ b/doc/source/reference/routines.polynomials.rst @@ -9,24 +9,165 @@ of the `numpy.polynomial` package, introduced in NumPy 1.4. Prior to NumPy 1.4, `numpy.poly1d` was the class of choice and it is still available in order to maintain backward compatibility. -However, the newer Polynomial package is more complete than `numpy.poly1d` -and its convenience classes are better behaved in the numpy environment. +However, the newer `polynomial package <numpy.polynomial>` is more complete +and its `convenience classes <routines.polynomials.classes>` provide a +more consistent, better-behaved interface for working with polynomial +expressions. Therefore :mod:`numpy.polynomial` is recommended for new coding. -Transition notice ------------------ -The various routines in the Polynomial package all deal with -series whose coefficients go from degree zero upward, -which is the *reverse order* of the Poly1d convention. -The easy way to remember this is that indexes -correspond to degree, i.e., coef[i] is the coefficient of the term of -degree i. +.. note:: **Terminology** + The term *polynomial module* refers to the old API defined in + `numpy.lib.polynomial`, which includes the :class:`numpy.poly1d` class and + the polynomial functions prefixed with *poly* accessible from the `numpy` + namespace (e.g. `numpy.polyadd`, `numpy.polyval`, `numpy.polyfit`, etc.). + + The term *polynomial package* refers to the new API definied in + `numpy.polynomial`, which includes the convenience classes for the + different kinds of polynomials (`numpy.polynomial.Polynomial`, + `numpy.polynomial.Chebyshev`, etc.). + +Transitioning from `numpy.poly1d` to `numpy.polynomial` +------------------------------------------------------- + +As noted above, the :class:`poly1d class <numpy.poly1d>` and associated +functions defined in ``numpy.lib.polynomial``, such as `numpy.polyfit` +and `numpy.poly`, are considered legacy and should **not** be used in new +code. +Since NumPy version 1.4, the `numpy.polynomial` package is preferred for +working with polynomials. + +Quick Reference +~~~~~~~~~~~~~~~ + +The following table highlights some of the main differences between the +legacy polynomial module and the polynomial package for common tasks. +The `~numpy.polynomial.polynomial.Polynomial` class is imported for brevity:: + + from numpy.polynomial import Polynomial + + ++------------------------+------------------------------+---------------------------------------+ +| **How to...** | Legacy (`numpy.poly1d`) | `numpy.polynomial` | ++------------------------+------------------------------+---------------------------------------+ +| Create a | ``p = np.poly1d([1, 2, 3])`` | ``p = Polynomial([3, 2, 1])`` | +| polynomial object | | | +| from coefficients [1]_ | | | ++------------------------+------------------------------+---------------------------------------+ +| Create a polynomial | ``r = np.poly([-1, 1])`` | ``p = Polynomial.fromroots([-1, 1])`` | +| object from roots | ``p = np.poly1d(r)`` | | ++------------------------+------------------------------+---------------------------------------+ +| Fit a polynomial of | | | +| degree ``deg`` to data | ``np.polyfit(x, y, deg)`` | ``Polynomial.fit(x, y, deg)`` | ++------------------------+------------------------------+---------------------------------------+ + + +.. [1] Note the reversed ordering of the coefficients + +Transition Guide +~~~~~~~~~~~~~~~~ + +There are significant differences between ``numpy.lib.polynomial`` and +`numpy.polynomial`. +The most significant difference is the ordering of the coefficients for the +polynomial expressions. +The various routines in `numpy.polynomial` all +deal with series whose coefficients go from degree zero upward, +which is the *reverse order* of the poly1d convention. +The easy way to remember this is that indices +correspond to degree, i.e., ``coef[i]`` is the coefficient of the term of +degree *i*. + +Though the difference in convention may be confusing, it is straightforward to +convert from the legacy polynomial API to the new. +For example, the following demonstrates how you would convert a `numpy.poly1d` +instance representing the expression :math:`x^{2} + 2x + 3` to a +`~numpy.polynomial.polynomial.Polynomial` instance representing the same +expression:: + + >>> p1d = np.poly1d([1, 2, 3]) + >>> p = np.polynomial.Polynomial(p1d.coef[::-1]) + +In addition to the ``coef`` attribute, polynomials from the polynomial +package also have ``domain`` and ``window`` attributes. +These attributes are most relevant when fitting +polynomials to data, though it should be noted that polynomials with +different ``domain`` and ``window`` attributes are not considered equal, and +can't be mixed in arithmetic:: + + >>> p1 = np.polynomial.Polynomial([1, 2, 3]) + >>> p1 + Polynomial([1., 2., 3.], domain=[-1, 1], window=[-1, 1]) + >>> p2 = np.polynomial.Polynomial([1, 2, 3], domain=[-2, 2]) + >>> p1 == p2 + False + >>> p1 + p2 + Traceback (most recent call last): + ... + TypeError: Domains differ + +See the documentation for the +`convenience classes <routines.polynomials.classes>`_ for further details on +the ``domain`` and ``window`` attributes. + +Another major difference bewteen the legacy polynomial module and the +polynomial package is polynomial fitting. In the old module, fitting was +done via the `~numpy.polyfit` function. In the polynomial package, the +`~numpy.polynomial.polynomial.Polynomial.fit` class method is preferred. For +example, consider a simple linear fit to the following data: + +.. ipython:: python + + rg = np.random.default_rng() + x = np.arange(10) + y = np.arange(10) + rg.standard_normal(10) + +With the legacy polynomial module, a linear fit (i.e. polynomial of degree 1) +could be applied to these data with `~numpy.polyfit`: + +.. ipython:: python + + np.polyfit(x, y, deg=1) + +With the new polynomial API, the `~numpy.polynomial.polynomial.Polynomial.fit` +class method is preferred: + +.. ipython:: python + + p_fitted = np.polynomial.Polynomial.fit(x, y, deg=1) + p_fitted + +Note that the coefficients are given *in the scaled domain* defined by the +linear mapping between the ``window`` and ``domain``. +`~numpy.polynomial.polynomial.Polynomial.convert` can be used to get the +coefficients in the unscaled data domain. + +.. ipython:: python + + p_fitted.convert() + +Documentation for the `~numpy.polynomial` Package +------------------------------------------------- + +In addition to standard power series polynomials, the polynomial package +provides several additional kinds of polynomials including Chebyshev, +Hermite (two subtypes), Laguerre, and Legendre polynomials. +Each of these has an associated +`convenience class <routines.polynomials.classes>` available from the +`numpy.polynomial` namespace that provides a consistent interface for working +with polynomials regardless of their type. .. toctree:: :maxdepth: 1 routines.polynomials.classes + +Documentation pertaining to specific functions defined for each kind of +polynomial individually can be found in the corresponding module documentation: + +.. toctree:: + :maxdepth: 1 + routines.polynomials.polynomial routines.polynomials.chebyshev routines.polynomials.hermite @@ -36,6 +177,9 @@ degree i. routines.polynomials.polyutils +Documentation for Legacy Polynomials +------------------------------------ + .. toctree:: :maxdepth: 2 diff --git a/doc/source/user/c-info.beyond-basics.rst b/doc/source/user/c-info.beyond-basics.rst index 124162d6c..289a7951b 100644 --- a/doc/source/user/c-info.beyond-basics.rst +++ b/doc/source/user/c-info.beyond-basics.rst @@ -172,8 +172,8 @@ iterators so that all that needs to be done to advance to the next element in each array is for PyArray_ITER_NEXT to be called for each of the inputs. This incrementing is automatically performed by :c:func:`PyArray_MultiIter_NEXT` ( ``obj`` ) macro (which can handle a -multiterator ``obj`` as either a :c:type:`PyArrayMultiObject *` or a -:c:type:`PyObject *<PyObject>`). The data from input number ``i`` is available using +multiterator ``obj`` as either a :c:expr:`PyArrayMultiObject *` or a +:c:expr:`PyObject *`). The data from input number ``i`` is available using :c:func:`PyArray_MultiIter_DATA` ( ``obj``, ``i`` ) and the total (broadcasted) size as :c:func:`PyArray_MultiIter_SIZE` ( ``obj``). An example of using this feature follows. @@ -400,7 +400,7 @@ describe the desired behavior of the type. Typically, a new C-structure is also created to contain the instance-specific information needed for each object of the type as well. For example, :c:data:`&PyArray_Type<PyArray_Type>` is a pointer to the type-object table for the ndarray -while a :c:type:`PyArrayObject *` variable is a pointer to a particular instance +while a :c:expr:`PyArrayObject *` variable is a pointer to a particular instance of an ndarray (one of the members of the ndarray structure is, in turn, a pointer to the type- object table :c:data:`&PyArray_Type<PyArray_Type>`). Finally :c:func:`PyType_Ready` (<pointer_to_type_object>) must be called for diff --git a/doc/source/user/c-info.how-to-extend.rst b/doc/source/user/c-info.how-to-extend.rst index 845ce0a74..ebb4b7518 100644 --- a/doc/source/user/c-info.how-to-extend.rst +++ b/doc/source/user/c-info.how-to-extend.rst @@ -174,7 +174,7 @@ rule. There are several converter functions defined in the NumPy C-API that may be of use. In particular, the :c:func:`PyArray_DescrConverter` function is very useful to support arbitrary data-type specification. This function transforms any valid data-type Python object into a -:c:type:`PyArray_Descr *` object. Remember to pass in the address of the +:c:expr:`PyArray_Descr *` object. Remember to pass in the address of the C-variables that should be filled in. There are lots of examples of how to use :c:func:`PyArg_ParseTuple` @@ -192,7 +192,7 @@ It is important to keep in mind that you get a *borrowed* reference to the object when using the "O" format string. However, the converter functions usually require some form of memory handling. In this example, if the conversion is successful, *dtype* will hold a new -reference to a :c:type:`PyArray_Descr *` object, while *input* will hold a +reference to a :c:expr:`PyArray_Descr *` object, while *input* will hold a borrowed reference. Therefore, if this conversion were mixed with another conversion (say to an integer) and the data-type conversion was successful but the integer conversion failed, then you would need @@ -213,9 +213,9 @@ The :c:func:`Py_BuildValue` (format_string, c_variables...) function makes it easy to build tuples of Python objects from C variables. Pay special attention to the difference between 'N' and 'O' in the format string or you can easily create memory leaks. The 'O' format string -increments the reference count of the :c:type:`PyObject *<PyObject>` C-variable it +increments the reference count of the :c:expr:`PyObject *` C-variable it corresponds to, while the 'N' format string steals a reference to the -corresponding :c:type:`PyObject *<PyObject>` C-variable. You should use 'N' if you have +corresponding :c:expr:`PyObject *` C-variable. You should use 'N' if you have already created a reference for the object and just want to give that reference to the tuple. You should use 'O' if you only have a borrowed reference to an object and need to create one to provide for the @@ -510,7 +510,7 @@ by providing default values for common use cases. Getting at ndarray memory and accessing elements of the ndarray --------------------------------------------------------------- -If obj is an ndarray (:c:type:`PyArrayObject *`), then the data-area of the +If obj is an ndarray (:c:expr:`PyArrayObject *`), then the data-area of the ndarray is pointed to by the void* pointer :c:func:`PyArray_DATA` (obj) or the char* pointer :c:func:`PyArray_BYTES` (obj). Remember that (in general) this data-area may not be aligned according to the data-type, it may diff --git a/doc/source/user/quickstart.rst b/doc/source/user/quickstart.rst index 8fdc6ec36..ab5bb5318 100644 --- a/doc/source/user/quickstart.rst +++ b/doc/source/user/quickstart.rst @@ -53,8 +53,8 @@ axis has a length of 2, the second axis has a length of 3. :: - [[ 1., 0., 0.], - [ 0., 1., 2.]] + [[1., 0., 0.], + [0., 1., 2.]] NumPy's array class is called ``ndarray``. It is also known by the alias ``array``. Note that ``numpy.array`` is not the same as the Standard @@ -128,7 +128,7 @@ from the type of the elements in the sequences. :: >>> import numpy as np - >>> a = np.array([2,3,4]) + >>> a = np.array([2, 3, 4]) >>> a array([2, 3, 4]) >>> a.dtype @@ -142,11 +142,11 @@ rather than providing a single sequence as an argument. :: - >>> a = np.array(1,2,3,4) # WRONG + >>> a = np.array(1, 2, 3, 4) # WRONG Traceback (most recent call last): ... TypeError: array() takes from 1 to 2 positional arguments but 4 were given - >>> a = np.array([1,2,3,4]) # RIGHT + >>> a = np.array([1, 2, 3, 4]) # RIGHT ``array`` transforms sequences of sequences into two-dimensional arrays, sequences of sequences of sequences into three-dimensional arrays, and @@ -154,7 +154,7 @@ so on. :: - >>> b = np.array([(1.5,2,3), (4,5,6)]) + >>> b = np.array([(1.5, 2, 3), (4, 5, 6)]) >>> b array([[1.5, 2. , 3. ], [4. , 5. , 6. ]]) @@ -163,7 +163,7 @@ The type of the array can also be explicitly specified at creation time: :: - >>> c = np.array( [ [1,2], [3,4] ], dtype=complex ) + >>> c = np.array([[1, 2], [3, 4]], dtype=complex) >>> c array([[1.+0.j, 2.+0.j], [3.+0.j, 4.+0.j]]) @@ -177,7 +177,7 @@ The function ``zeros`` creates an array full of zeros, the function ``ones`` creates an array full of ones, and the function ``empty`` creates an array whose initial content is random and depends on the state of the memory. By default, the dtype of the created array is -``float64``. +``float64``, but it can be specified via the key word argument ``dtype``. :: @@ -185,7 +185,7 @@ state of the memory. By default, the dtype of the created array is array([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]) - >>> np.ones( (2,3,4), dtype=np.int16 ) # dtype can also be specified + >>> np.ones((2, 3, 4), dtype=np.int16) array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], @@ -193,9 +193,9 @@ state of the memory. By default, the dtype of the created array is [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]], dtype=int16) - >>> np.empty( (2,3) ) # uninitialized - array([[ 3.73603959e-262, 6.02658058e-154, 6.55490914e-260], # may vary - [ 5.30498948e-313, 3.14673309e-307, 1.00000000e+000]]) + >>> np.empty((2, 3)) + array([[3.73603959e-262, 6.02658058e-154, 6.55490914e-260], # may vary + [5.30498948e-313, 3.14673309e-307, 1.00000000e+000]]) To create sequences of numbers, NumPy provides the ``arange`` function which is analogous to the Python built-in ``range``, but returns an @@ -203,9 +203,9 @@ array. :: - >>> np.arange( 10, 30, 5 ) + >>> np.arange(10, 30, 5) array([10, 15, 20, 25]) - >>> np.arange( 0, 2, 0.3 ) # it accepts float arguments + >>> np.arange(0, 2, 0.3) # it accepts float arguments array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8]) When ``arange`` is used with floating point arguments, it is generally @@ -215,9 +215,9 @@ to use the function ``linspace`` that receives as an argument the number of elements that we want, instead of the step:: >>> from numpy import pi - >>> np.linspace( 0, 2, 9 ) # 9 numbers from 0 to 2 + >>> np.linspace(0, 2, 9) # 9 numbers from 0 to 2 array([0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ]) - >>> x = np.linspace( 0, 2*pi, 100 ) # useful to evaluate function at lots of points + >>> x = np.linspace(0, 2 * pi, 100) # useful to evaluate function at lots of points >>> f = np.sin(x) .. seealso:: @@ -251,18 +251,18 @@ matrices and tridimensionals as lists of matrices. :: - >>> a = np.arange(6) # 1d array + >>> a = np.arange(6) # 1d array >>> print(a) [0 1 2 3 4 5] - >>> - >>> b = np.arange(12).reshape(4,3) # 2d array + >>> + >>> b = np.arange(12).reshape(4, 3) # 2d array >>> print(b) [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]] - >>> - >>> c = np.arange(24).reshape(2,3,4) # 3d array + >>> + >>> c = np.arange(24).reshape(2, 3, 4) # 3d array >>> print(c) [[[ 0 1 2 3] [ 4 5 6 7] @@ -280,8 +280,8 @@ central part of the array and only prints the corners:: >>> print(np.arange(10000)) [ 0 1 2 ... 9997 9998 9999] - >>> - >>> print(np.arange(10000).reshape(100,100)) + >>> + >>> print(np.arange(10000).reshape(100, 100)) [[ 0 1 2 ... 97 98 99] [ 100 101 102 ... 197 198 199] [ 200 201 202 ... 297 298 299] @@ -295,7 +295,7 @@ can change the printing options using ``set_printoptions``. :: - >>> np.set_printoptions(threshold=sys.maxsize) # sys module should be imported + >>> np.set_printoptions(threshold=sys.maxsize) # sys module should be imported .. _quickstart.basic-operations: @@ -308,35 +308,35 @@ created and filled with the result. :: - >>> a = np.array( [20,30,40,50] ) - >>> b = np.arange( 4 ) + >>> a = np.array([20, 30, 40, 50]) + >>> b = np.arange(4) >>> b array([0, 1, 2, 3]) - >>> c = a-b + >>> c = a - b >>> c array([20, 29, 38, 47]) >>> b**2 array([0, 1, 4, 9]) - >>> 10*np.sin(a) + >>> 10 * np.sin(a) array([ 9.12945251, -9.88031624, 7.4511316 , -2.62374854]) - >>> a<35 + >>> a < 35 array([ True, True, False, False]) Unlike in many matrix languages, the product operator ``*`` operates elementwise in NumPy arrays. The matrix product can be performed using the ``@`` operator (in python >=3.5) or the ``dot`` function or method:: - >>> A = np.array( [[1,1], - ... [0,1]] ) - >>> B = np.array( [[2,0], - ... [3,4]] ) - >>> A * B # elementwise product + >>> A = np.array([[1, 1], + ... [0, 1]]) + >>> B = np.array([[2, 0], + ... [3, 4]]) + >>> A * B # elementwise product array([[2, 0], [0, 4]]) - >>> A @ B # matrix product + >>> A @ B # matrix product array([[5, 4], [3, 4]]) - >>> A.dot(B) # another matrix product + >>> A.dot(B) # another matrix product array([[5, 4], [3, 4]]) @@ -345,9 +345,9 @@ existing array rather than create a new one. :: - >>> rg = np.random.default_rng(1) # create instance of default random number generator - >>> a = np.ones((2,3), dtype=int) - >>> b = rg.random((2,3)) + >>> rg = np.random.default_rng(1) # create instance of default random number generator + >>> a = np.ones((2, 3), dtype=int) + >>> b = rg.random((2, 3)) >>> a *= 3 >>> a array([[3, 3, 3], @@ -356,7 +356,7 @@ existing array rather than create a new one. >>> b array([[3.51182162, 3.9504637 , 3.14415961], [3.94864945, 3.31183145, 3.42332645]]) - >>> a += b # b is not automatically converted to integer type + >>> a += b # b is not automatically converted to integer type Traceback (most recent call last): ... numpy.core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind' @@ -368,15 +368,15 @@ as upcasting). :: >>> a = np.ones(3, dtype=np.int32) - >>> b = np.linspace(0,pi,3) + >>> b = np.linspace(0, pi, 3) >>> b.dtype.name 'float64' - >>> c = a+b + >>> c = a + b >>> c array([1. , 2.57079633, 4.14159265]) >>> c.dtype.name 'float64' - >>> d = np.exp(c*1j) + >>> d = np.exp(c * 1j) >>> d array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j, -0.54030231-0.84147098j]) @@ -388,7 +388,7 @@ the array, are implemented as methods of the ``ndarray`` class. :: - >>> a = rg.random((2,3)) + >>> a = rg.random((2, 3)) >>> a array([[0.82770259, 0.40919914, 0.54959369], [0.02755911, 0.75351311, 0.53814331]]) @@ -404,19 +404,19 @@ of numbers, regardless of its shape. However, by specifying the ``axis`` parameter you can apply an operation along the specified axis of an array:: - >>> b = np.arange(12).reshape(3,4) + >>> b = np.arange(12).reshape(3, 4) >>> b array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> - >>> b.sum(axis=0) # sum of each column + >>> b.sum(axis=0) # sum of each column array([12, 15, 18, 21]) >>> - >>> b.min(axis=1) # min of each row + >>> b.min(axis=1) # min of each row array([0, 4, 8]) >>> - >>> b.cumsum(axis=1) # cumulative sum along each row + >>> b.cumsum(axis=1) # cumulative sum along each row array([[ 0, 1, 3, 6], [ 4, 9, 15, 22], [ 8, 17, 27, 38]]) @@ -427,7 +427,7 @@ Universal Functions NumPy provides familiar mathematical functions such as sin, cos, and exp. In NumPy, these are called "universal -functions"(\ ``ufunc``). Within NumPy, these functions +functions" (\ ``ufunc``). Within NumPy, these functions operate elementwise on an array, producing an array as output. :: @@ -507,15 +507,15 @@ and other Python sequences. 8 >>> a[2:5] array([ 8, 27, 64]) - # equivalent to a[0:6:2] = 1000; - # from start to position 6, exclusive, set every 2nd element to 1000 + >>> # equivalent to a[0:6:2] = 1000; + >>> # from start to position 6, exclusive, set every 2nd element to 1000 >>> a[:6:2] = 1000 >>> a array([1000, 1, 1000, 27, 1000, 125, 216, 343, 512, 729]) - >>> a[ : :-1] # reversed a + >>> a[::-1] # reversed a array([ 729, 512, 343, 216, 125, 1000, 27, 1000, 1, 1000]) >>> for i in a: - ... print(i**(1/3.)) + ... print(i**(1 / 3.)) ... 9.999999999999998 1.0 @@ -532,23 +532,23 @@ and other Python sequences. **Multidimensional** arrays can have one index per axis. These indices are given in a tuple separated by commas:: - >>> def f(x,y): - ... return 10*x+y + >>> def f(x, y): + ... return 10 * x + y ... - >>> b = np.fromfunction(f,(5,4),dtype=int) + >>> b = np.fromfunction(f, (5, 4), dtype=int) >>> b array([[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23], [30, 31, 32, 33], [40, 41, 42, 43]]) - >>> b[2,3] + >>> b[2, 3] 23 - >>> b[0:5, 1] # each row in the second column of b + >>> b[0:5, 1] # each row in the second column of b array([ 1, 11, 21, 31, 41]) - >>> b[ : ,1] # equivalent to the previous example + >>> b[:, 1] # equivalent to the previous example array([ 1, 11, 21, 31, 41]) - >>> b[1:3, : ] # each column in the second and third row of b + >>> b[1:3, :] # each column in the second and third row of b array([[10, 11, 12, 13], [20, 21, 22, 23]]) @@ -557,34 +557,34 @@ indices are considered complete slices\ ``:`` :: - >>> b[-1] # the last row. Equivalent to b[-1,:] + >>> b[-1] # the last row. Equivalent to b[-1, :] array([40, 41, 42, 43]) The expression within brackets in ``b[i]`` is treated as an ``i`` followed by as many instances of ``:`` as needed to represent the remaining axes. NumPy also allows you to write this using dots as -``b[i,...]``. +``b[i, ...]``. The **dots** (``...``) represent as many colons as needed to produce a complete indexing tuple. For example, if ``x`` is an array with 5 axes, then -- ``x[1,2,...]`` is equivalent to ``x[1,2,:,:,:]``, -- ``x[...,3]`` to ``x[:,:,:,:,3]`` and -- ``x[4,...,5,:]`` to ``x[4,:,:,5,:]``. +- ``x[1, 2, ...]`` is equivalent to ``x[1, 2, :, :, :]``, +- ``x[..., 3]`` to ``x[:, :, :, :, 3]`` and +- ``x[4, ..., 5, :]`` to ``x[4, :, :, 5, :]``. :: - >>> c = np.array( [[[ 0, 1, 2], # a 3D array (two stacked 2D arrays) - ... [ 10, 12, 13]], - ... [[100,101,102], - ... [110,112,113]]]) + >>> c = np.array([[[ 0, 1, 2], # a 3D array (two stacked 2D arrays) + ... [ 10, 12, 13]], + ... [[100, 101, 102], + ... [110, 112, 113]]]) >>> c.shape (2, 2, 3) - >>> c[1,...] # same as c[1,:,:] or c[1] + >>> c[1, ...] # same as c[1, :, :] or c[1] array([[100, 101, 102], [110, 112, 113]]) - >>> c[...,2] # same as c[:,:,2] + >>> c[..., 2] # same as c[:, :, 2] array([[ 2, 13], [102, 113]]) @@ -647,7 +647,7 @@ Changing the shape of an array An array has a shape given by the number of elements along each axis:: - >>> a = np.floor(10*rg.random((3,4))) + >>> a = np.floor(10 * rg.random((3, 4))) >>> a array([[3., 7., 3., 4.], [1., 4., 2., 2.], @@ -661,7 +661,7 @@ the original array:: >>> a.ravel() # returns the array, flattened array([3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.]) - >>> a.reshape(6,2) # returns the array with a modified shape + >>> a.reshape(6, 2) # returns the array with a modified shape array([[3., 7.], [3., 4.], [1., 4.], @@ -678,14 +678,14 @@ the original array:: >>> a.shape (3, 4) -The order of the elements in the array resulting from ravel() is +The order of the elements in the array resulting from ``ravel`` is normally "C-style", that is, the rightmost index "changes the fastest", -so the element after a[0,0] is a[0,1]. If the array is reshaped to some +so the element after ``a[0, 0]`` is ``a[0, 1]``. If the array is reshaped to some other shape, again the array is treated as "C-style". NumPy normally -creates arrays stored in this order, so ravel() will usually not need to +creates arrays stored in this order, so ``ravel`` will usually not need to copy its argument, but if the array was made by taking slices of another array or created with unusual options, it may need to be copied. The -functions ravel() and reshape() can also be instructed, using an +functions ``ravel`` and ``reshape`` can also be instructed, using an optional argument, to use FORTRAN-style arrays, in which the leftmost index changes the fastest. @@ -698,15 +698,15 @@ itself:: array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]]) - >>> a.resize((2,6)) + >>> a.resize((2, 6)) >>> a array([[3., 7., 3., 4., 1., 4.], [2., 2., 7., 2., 4., 9.]]) -If a dimension is given as -1 in a reshaping operation, the other +If a dimension is given as ``-1`` in a reshaping operation, the other dimensions are automatically calculated:: - >>> a.reshape(3,-1) + >>> a.reshape(3, -1) array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]]) @@ -726,45 +726,44 @@ Stacking together different arrays Several arrays can be stacked together along different axes:: - >>> a = np.floor(10*rg.random((2,2))) + >>> a = np.floor(10 * rg.random((2, 2))) >>> a array([[9., 7.], [5., 2.]]) - >>> b = np.floor(10*rg.random((2,2))) + >>> b = np.floor(10 * rg.random((2, 2))) >>> b array([[1., 9.], [5., 1.]]) - >>> np.vstack((a,b)) + >>> np.vstack((a, b)) array([[9., 7.], [5., 2.], [1., 9.], [5., 1.]]) - >>> np.hstack((a,b)) + >>> np.hstack((a, b)) array([[9., 7., 1., 9.], [5., 2., 5., 1.]]) -The function `column_stack` -stacks 1D arrays as columns into a 2D array. It is equivalent to -`hstack` only for 2D arrays:: +The function `column_stack` stacks 1D arrays as columns into a 2D array. +It is equivalent to `hstack` only for 2D arrays:: >>> from numpy import newaxis - >>> np.column_stack((a,b)) # with 2D arrays + >>> np.column_stack((a, b)) # with 2D arrays array([[9., 7., 1., 9.], [5., 2., 5., 1.]]) - >>> a = np.array([4.,2.]) - >>> b = np.array([3.,8.]) - >>> np.column_stack((a,b)) # returns a 2D array + >>> a = np.array([4., 2.]) + >>> b = np.array([3., 8.]) + >>> np.column_stack((a, b)) # returns a 2D array array([[4., 3.], [2., 8.]]) - >>> np.hstack((a,b)) # the result is different + >>> np.hstack((a, b)) # the result is different array([4., 2., 3., 8.]) - >>> a[:,newaxis] # view `a` as a 2D column vector + >>> a[:, newaxis] # view `a` as a 2D column vector array([[4.], [2.]]) - >>> np.column_stack((a[:,newaxis],b[:,newaxis])) + >>> np.column_stack((a[:, newaxis], b[:, newaxis])) array([[4., 3.], [2., 8.]]) - >>> np.hstack((a[:,newaxis],b[:,newaxis])) # the result is the same + >>> np.hstack((a[:, newaxis], b[:, newaxis])) # the result is the same array([[4., 3.], [2., 8.]]) @@ -785,12 +784,10 @@ which the concatenation should happen. **Note** -In complex cases, `r_` and -`c_` are useful for creating arrays -by stacking numbers along one axis. They allow the use of range literals -(":") :: +In complex cases, `r_` and `c_` are useful for creating arrays by stacking +numbers along one axis. They allow the use of range literals ``:``. :: - >>> np.r_[1:4,0,4] + >>> np.r_[1:4, 0, 4] array([1, 2, 3, 0, 4]) When used with arrays as arguments, @@ -818,18 +815,18 @@ array along its horizontal axis, either by specifying the number of equally shaped arrays to return, or by specifying the columns after which the division should occur:: - >>> a = np.floor(10*rg.random((2,12))) + >>> a = np.floor(10 * rg.random((2, 12))) >>> a array([[6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.], [8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.]]) - # Split a into 3 - >>> np.hsplit(a,3) + >>> # Split `a` into 3 + >>> np.hsplit(a, 3) [array([[6., 7., 6., 9.], [8., 5., 5., 7.]]), array([[0., 5., 4., 0.], [1., 8., 6., 7.]]), array([[6., 8., 5., 2.], [1., 8., 1., 0.]])] - # Split a after the third and the fourth column - >>> np.hsplit(a,(3,4)) + >>> # Split `a` after the third and the fourth column + >>> np.hsplit(a, (3, 4)) [array([[6., 7., 6.], [8., 5., 5.]]), array([[9.], [7.]]), array([[0., 5., 4., 0., 6., 8., 5., 2.], @@ -871,7 +868,7 @@ copy. >>> def f(x): ... print(id(x)) ... - >>> id(a) # id is a unique identifier of an object + >>> id(a) # id is a unique identifier of an object 148293216 # may vary >>> f(a) 148293216 # may vary @@ -887,15 +884,15 @@ creates a new array object that looks at the same data. >>> c = a.view() >>> c is a False - >>> c.base is a # c is a view of the data owned by a + >>> c.base is a # c is a view of the data owned by a True >>> c.flags.owndata False >>> - >>> c = c.reshape((2, 6)) # a's shape doesn't change + >>> c = c.reshape((2, 6)) # a's shape doesn't change >>> a.shape (3, 4) - >>> c[0, 4] = 1234 # a's data changes + >>> c[0, 4] = 1234 # a's data changes >>> a array([[ 0, 1, 2, 3], [1234, 5, 6, 7], @@ -903,8 +900,8 @@ creates a new array object that looks at the same data. Slicing an array returns a view of it:: - >>> s = a[ : , 1:3] # spaces added for clarity; could also be written "s = a[:, 1:3]" - >>> s[:] = 10 # s[:] is a view of s. Note the difference between s = 10 and s[:] = 10 + >>> s = a[:, 1:3] + >>> s[:] = 10 # s[:] is a view of s. Note the difference between s = 10 and s[:] = 10 >>> a array([[ 0, 10, 10, 3], [1234, 10, 10, 7], @@ -917,12 +914,12 @@ The ``copy`` method makes a complete copy of the array and its data. :: - >>> d = a.copy() # a new array object with new data is created + >>> d = a.copy() # a new array object with new data is created >>> d is a False - >>> d.base is a # d doesn't share anything with a + >>> d.base is a # d doesn't share anything with a False - >>> d[0,0] = 9999 + >>> d[0, 0] = 9999 >>> a array([[ 0, 10, 10, 3], [1234, 10, 10, 7], @@ -1068,13 +1065,13 @@ Indexing with Arrays of Indices :: - >>> a = np.arange(12)**2 # the first 12 square numbers - >>> i = np.array([1, 1, 3, 8, 5]) # an array of indices - >>> a[i] # the elements of a at the positions i + >>> a = np.arange(12)**2 # the first 12 square numbers + >>> i = np.array([1, 1, 3, 8, 5]) # an array of indices + >>> a[i] # the elements of `a` at the positions `i` array([ 1, 1, 9, 64, 25]) - >>> - >>> j = np.array([[3, 4], [9, 7]]) # a bidimensional array of indices - >>> a[j] # the same shape as j + >>> + >>> j = np.array([[3, 4], [9, 7]]) # a bidimensional array of indices + >>> a[j] # the same shape as `j` array([[ 9, 16], [81, 49]]) @@ -1090,9 +1087,9 @@ using a palette. ... [0, 255, 0], # green ... [0, 0, 255], # blue ... [255, 255, 255]]) # white - >>> image = np.array([[0, 1, 2, 0], # each value corresponds to a color in the palette + >>> image = np.array([[0, 1, 2, 0], # each value corresponds to a color in the palette ... [0, 3, 4, 0]]) - >>> palette[image] # the (2, 4, 3) color image + >>> palette[image] # the (2, 4, 3) color image array([[[ 0, 0, 0], [255, 0, 0], [ 0, 255, 0], @@ -1108,25 +1105,25 @@ indices for each dimension must have the same shape. :: - >>> a = np.arange(12).reshape(3,4) + >>> a = np.arange(12).reshape(3, 4) >>> a array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) - >>> i = np.array([[0, 1], # indices for the first dim of a + >>> i = np.array([[0, 1], # indices for the first dim of `a` ... [1, 2]]) - >>> j = np.array([[2, 1], # indices for the second dim + >>> j = np.array([[2, 1], # indices for the second dim ... [3, 3]]) - >>> - >>> a[i, j] # i and j must have equal shape + >>> + >>> a[i, j] # i and j must have equal shape array([[ 2, 5], [ 7, 11]]) - >>> + >>> >>> a[i, 2] array([[ 2, 6], [ 6, 10]]) - >>> - >>> a[:, j] # i.e., a[ : , j] + >>> + >>> a[:, j] array([[[ 2, 1], [ 3, 3]], <BLANKLINE> @@ -1142,26 +1139,24 @@ put ``i`` and ``j`` in a ``tuple`` and then do the indexing with that. :: >>> l = (i, j) - # equivalent to a[i, j] + >>> # equivalent to a[i, j] >>> a[l] array([[ 2, 5], [ 7, 11]]) However, we can not do this by putting ``i`` and ``j`` into an array, because this array will be interpreted as indexing the first dimension -of a. +of ``a``. :: >>> s = np.array([i, j]) - - # not what we want + >>> # not what we want >>> a[s] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: index 3 is out of bounds for axis 0 with size 3 - - # same as a[i, j] + >>> # same as `a[i, j]` >>> a[tuple(s)] array([[ 2, 5], [ 7, 11]]) @@ -1169,8 +1164,8 @@ of a. Another common use of indexing with arrays is the search of the maximum value of time-dependent series:: - >>> time = np.linspace(20, 145, 5) # time scale - >>> data = np.sin(np.arange(20)).reshape(5,4) # 4 time-dependent series + >>> time = np.linspace(20, 145, 5) # time scale + >>> data = np.sin(np.arange(20)).reshape(5, 4) # 4 time-dependent series >>> time array([ 20. , 51.25, 82.5 , 113.75, 145. ]) >>> data @@ -1179,22 +1174,18 @@ value of time-dependent series:: [ 0.98935825, 0.41211849, -0.54402111, -0.99999021], [-0.53657292, 0.42016704, 0.99060736, 0.65028784], [-0.28790332, -0.96139749, -0.75098725, 0.14987721]]) - - # index of the maxima for each series + >>> # index of the maxima for each series >>> ind = data.argmax(axis=0) >>> ind array([2, 0, 3, 1]) - - # times corresponding to the maxima + >>> # times corresponding to the maxima >>> time_max = time[ind] - >>> - >>> data_max = data[ind, range(data.shape[1])] # => data[ind[0],0], data[ind[1],1]... - + >>> + >>> data_max = data[ind, range(data.shape[1])] # => data[ind[0], 0], data[ind[1], 1]... >>> time_max array([ 82.5 , 20. , 113.75, 51.25]) >>> data_max array([0.98935825, 0.84147098, 0.99060736, 0.6569866 ]) - >>> np.all(data_max == data.max(axis=0)) True @@ -1203,7 +1194,7 @@ You can also use indexing with arrays as a target to assign to:: >>> a = np.arange(5) >>> a array([0, 1, 2, 3, 4]) - >>> a[[1,3,4]] = 0 + >>> a[[1, 3, 4]] = 0 >>> a array([0, 0, 2, 0, 0]) @@ -1211,7 +1202,7 @@ However, when the list of indices contains repetitions, the assignment is done several times, leaving behind the last value:: >>> a = np.arange(5) - >>> a[[0,0,2]]=[1,2,3] + >>> a[[0, 0, 2]] = [1, 2, 3] >>> a array([2, 1, 3, 3, 4]) @@ -1219,13 +1210,13 @@ This is reasonable enough, but watch out if you want to use Python's ``+=`` construct, as it may not do what you expect:: >>> a = np.arange(5) - >>> a[[0,0,2]]+=1 + >>> a[[0, 0, 2]] += 1 >>> a array([1, 1, 3, 3, 4]) Even though 0 occurs twice in the list of indices, the 0th element is -only incremented once. This is because Python requires "a+=1" to be -equivalent to "a = a + 1". +only incremented once. This is because Python requires ``a += 1`` to be +equivalent to ``a = a + 1``. Indexing with Boolean Arrays ---------------------------- @@ -1238,18 +1229,18 @@ which ones we don't. The most natural way one can think of for boolean indexing is to use boolean arrays that have *the same shape* as the original array:: - >>> a = np.arange(12).reshape(3,4) + >>> a = np.arange(12).reshape(3, 4) >>> b = a > 4 - >>> b # b is a boolean with a's shape + >>> b # `b` is a boolean with `a`'s shape array([[False, False, False, False], [False, True, True, True], [ True, True, True, True]]) - >>> a[b] # 1d array with the selected elements + >>> a[b] # 1d array with the selected elements array([ 5, 6, 7, 8, 9, 10, 11]) This property can be very useful in assignments:: - >>> a[b] = 0 # All elements of 'a' higher than 4 become 0 + >>> a[b] = 0 # All elements of `a` higher than 4 become 0 >>> a array([[0, 1, 2, 3], [4, 0, 0, 0], @@ -1264,45 +1255,45 @@ set <https://en.wikipedia.org/wiki/Mandelbrot_set>`__: >>> import numpy as np >>> import matplotlib.pyplot as plt - >>> def mandelbrot( h,w, maxit=20 ): + >>> def mandelbrot(h, w, maxit=20): ... """Returns an image of the Mandelbrot fractal of size (h,w).""" - ... y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ] - ... c = x+y*1j + ... y, x = np.ogrid[-1.4:1.4:h*1j, -2:0.8:w*1j] + ... c = x + y * 1j ... z = c ... divtime = maxit + np.zeros(z.shape, dtype=int) ... ... for i in range(maxit): ... z = z**2 + c - ... diverge = z*np.conj(z) > 2**2 # who is diverging - ... div_now = diverge & (divtime==maxit) # who is diverging now - ... divtime[div_now] = i # note when - ... z[diverge] = 2 # avoid diverging too much + ... diverge = z * np.conj(z) > 2**2 # who is diverging + ... div_now = diverge & (divtime == maxit) # who is diverging now + ... divtime[div_now] = i # note when + ... z[diverge] = 2 # avoid diverging too much ... ... return divtime - >>> plt.imshow(mandelbrot(400,400)) + >>> plt.imshow(mandelbrot(400, 400)) The second way of indexing with booleans is more similar to integer indexing; for each dimension of the array we give a 1D boolean array selecting the slices we want:: - >>> a = np.arange(12).reshape(3,4) - >>> b1 = np.array([False,True,True]) # first dim selection - >>> b2 = np.array([True,False,True,False]) # second dim selection - >>> - >>> a[b1,:] # selecting rows + >>> a = np.arange(12).reshape(3, 4) + >>> b1 = np.array([False, True, True]) # first dim selection + >>> b2 = np.array([True, False, True, False]) # second dim selection + >>> + >>> a[b1, :] # selecting rows array([[ 4, 5, 6, 7], [ 8, 9, 10, 11]]) - >>> - >>> a[b1] # same thing + >>> + >>> a[b1] # same thing array([[ 4, 5, 6, 7], [ 8, 9, 10, 11]]) - >>> - >>> a[:,b2] # selecting columns + >>> + >>> a[:, b2] # selecting columns array([[ 0, 2], [ 4, 6], [ 8, 10]]) - >>> - >>> a[b1,b2] # a weird thing to do + >>> + >>> a[b1, b2] # a weird thing to do array([ 4, 10]) Note that the length of the 1D boolean array must coincide with the @@ -1319,10 +1310,10 @@ obtain the result for each n-uplet. For example, if you want to compute all the a+b\*c for all the triplets taken from each of the vectors a, b and c:: - >>> a = np.array([2,3,4,5]) - >>> b = np.array([8,5,4]) - >>> c = np.array([5,4,6,8,3]) - >>> ax,bx,cx = np.ix_(a,b,c) + >>> a = np.array([2, 3, 4, 5]) + >>> b = np.array([8, 5, 4]) + >>> c = np.array([5, 4, 6, 8, 3]) + >>> ax, bx, cx = np.ix_(a, b, c) >>> ax array([[[2]], <BLANKLINE> @@ -1339,7 +1330,7 @@ and c:: array([[[5, 4, 6, 8, 3]]]) >>> ax.shape, bx.shape, cx.shape ((4, 1, 1), (1, 3, 1), (1, 1, 5)) - >>> result = ax+bx*cx + >>> result = ax + bx * cx >>> result array([[[42, 34, 50, 66, 26], [27, 22, 32, 42, 17], @@ -1356,9 +1347,9 @@ and c:: [[45, 37, 53, 69, 29], [30, 25, 35, 45, 20], [25, 21, 29, 37, 17]]]) - >>> result[3,2,4] + >>> result[3, 2, 4] 17 - >>> a[3]+b[2]*c[4] + >>> a[3] + b[2] * c[4] 17 You could also implement the reduce as follows:: @@ -1367,12 +1358,12 @@ You could also implement the reduce as follows:: ... vs = np.ix_(*vectors) ... r = ufct.identity ... for v in vs: - ... r = ufct(r,v) + ... r = ufct(r, v) ... return r and then use it as:: - >>> ufunc_reduce(np.add,a,b,c) + >>> ufunc_reduce(np.add, a, b, c) array([[[15, 14, 16, 18, 13], [12, 11, 13, 15, 10], [11, 10, 12, 14, 9]], @@ -1417,33 +1408,26 @@ See linalg.py in numpy folder for more. >>> print(a) [[1. 2.] [3. 4.]] - >>> a.transpose() array([[1., 3.], [2., 4.]]) - >>> np.linalg.inv(a) array([[-2. , 1. ], [ 1.5, -0.5]]) - - >>> u = np.eye(2) # unit 2x2 matrix; "eye" represents "I" + >>> u = np.eye(2) # unit 2x2 matrix; "eye" represents "I" >>> u array([[1., 0.], [0., 1.]]) >>> j = np.array([[0.0, -1.0], [1.0, 0.0]]) - - >>> j @ j # matrix product + >>> j @ j # matrix product array([[-1., 0.], [ 0., -1.]]) - >>> np.trace(u) # trace 2.0 - >>> y = np.array([[5.], [7.]]) >>> np.linalg.solve(a, y) array([[-3.], [ 4.]]) - >>> np.linalg.eig(j) (array([0.+1.j, 0.-1.j]), array([[0.70710678+0.j , 0.70710678-0.j ], [0. -0.70710678j, 0. +0.70710678j]])) @@ -1455,7 +1439,7 @@ See linalg.py in numpy folder for more. Returns The eigenvalues, each repeated according to its multiplicity. The normalized (unit "length") eigenvectors, such that the - column ``v[:,i]`` is the eigenvector corresponding to the + column ``v[:, i]`` is the eigenvector corresponding to the eigenvalue ``w[i]`` . Tricks and Tips @@ -1496,13 +1480,13 @@ functions ``column_stack``, ``dstack``, ``hstack`` and ``vstack``, depending on the dimension in which the stacking is to be done. For example:: - >>> x = np.arange(0,10,2) + >>> x = np.arange(0, 10, 2) >>> y = np.arange(5) - >>> m = np.vstack([x,y]) + >>> m = np.vstack([x, y]) >>> m array([[0, 2, 4, 6, 8], [0, 1, 2, 3, 4]]) - >>> xy = np.hstack([x,y]) + >>> xy = np.hstack([x, y]) >>> xy array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4]) @@ -1530,12 +1514,12 @@ that ``pylab.hist`` plots the histogram automatically, while >>> import matplotlib.pyplot as plt >>> # Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2 >>> mu, sigma = 2, 0.5 - >>> v = rg.normal(mu,sigma,10000) + >>> v = rg.normal(mu, sigma, 10000) >>> # Plot a normalized histogram with 50 bins >>> plt.hist(v, bins=50, density=1) # matplotlib version (plot) >>> # Compute the histogram with numpy and then plot it >>> (n, bins) = np.histogram(v, bins=50, density=True) # NumPy version (no plot) - >>> plt.plot(.5*(bins[1:]+bins[:-1]), n) + >>> plt.plot(.5 * (bins[1:] + bins[:-1]), n) Further reading diff --git a/doc_requirements.txt b/doc_requirements.txt index f69cc5dcb..0650e0a58 100644 --- a/doc_requirements.txt +++ b/doc_requirements.txt @@ -1,4 +1,4 @@ -sphinx>=2.2.0,<3.0 +sphinx>=3.2 numpydoc==1.1.0 ipython scipy diff --git a/numpy/__init__.py b/numpy/__init__.py index 879e8f013..a242bb7df 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -389,7 +389,12 @@ else: # Note that this will currently only make a difference on Linux core.multiarray._set_madvise_hugepage(use_hugepage) + # Give a warning if NumPy is reloaded or imported on a sub-interpreter + # We do this from python, since the C-module may not be reloaded and + # it is tidier organized. + core.multiarray._multiarray_umath._reload_guard() from ._version import get_versions __version__ = get_versions()['version'] del get_versions + diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index e2bf6c439..2cbfe52be 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -1147,13 +1147,13 @@ add_newdoc('numpy.core.multiarray', 'compare_chararrays', add_newdoc('numpy.core.multiarray', 'fromiter', """ - fromiter(iterable, dtype, count=-1, *, like=None) + fromiter(iter, dtype, count=-1, *, like=None) Create a new 1-dimensional array from an iterable object. Parameters ---------- - iterable : iterable object + iter : iterable object An iterable object providing data for the array. dtype : data-type The data-type of the returned array. diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py index f736973de..07179a627 100644 --- a/numpy/core/multiarray.py +++ b/numpy/core/multiarray.py @@ -259,12 +259,16 @@ def inner(a, b): Returns ------- out : ndarray - `out.shape = a.shape[:-1] + b.shape[:-1]` + If `a` and `b` are both + scalars or both 1-D arrays then a scalar is returned; otherwise + an array is returned. + ``out.shape = (*a.shape[:-1], *b.shape[:-1])`` Raises ------ ValueError - If the last dimension of `a` and `b` has different size. + If both `a` and `b` are nonscalar and their last dimensions have + different sizes. See Also -------- @@ -284,8 +288,8 @@ def inner(a, b): or explicitly:: - np.inner(a, b)[i0,...,ir-1,j0,...,js-1] - = sum(a[i0,...,ir-1,:]*b[j0,...,js-1,:]) + np.inner(a, b)[i0,...,ir-2,j0,...,js-2] + = sum(a[i0,...,ir-2,:]*b[j0,...,js-2,:]) In addition `a` or `b` may be scalars, in which case:: @@ -300,14 +304,25 @@ def inner(a, b): >>> np.inner(a, b) 2 - A multidimensional example: + Some multidimensional examples: >>> a = np.arange(24).reshape((2,3,4)) >>> b = np.arange(4) - >>> np.inner(a, b) + >>> c = np.inner(a, b) + >>> c.shape + (2, 3) + >>> c array([[ 14, 38, 62], [ 86, 110, 134]]) + >>> a = np.arange(2).reshape((1,1,2)) + >>> b = np.arange(6).reshape((3,2)) + >>> c = np.inner(a, b) + >>> c.shape + (1, 1, 3) + >>> c + array([[[1, 3, 5]]]) + An example where `b` is a scalar: >>> np.inner(np.eye(2), 7) diff --git a/numpy/core/src/multiarray/array_coercion.c b/numpy/core/src/multiarray/array_coercion.c index 53d891049..603e9d93b 100644 --- a/numpy/core/src/multiarray/array_coercion.c +++ b/numpy/core/src/multiarray/array_coercion.c @@ -979,14 +979,28 @@ PyArray_DiscoverDTypeAndShape_Recursive( * and to handle it recursively. That is, unless we have hit the * dimension limit. */ - npy_bool is_sequence = (PySequence_Check(obj) && PySequence_Size(obj) >= 0); + npy_bool is_sequence = PySequence_Check(obj); + if (is_sequence) { + is_sequence = PySequence_Size(obj) >= 0; + if (NPY_UNLIKELY(!is_sequence)) { + /* NOTE: This should likely just raise all errors */ + if (PyErr_ExceptionMatches(PyExc_RecursionError) || + PyErr_ExceptionMatches(PyExc_MemoryError)) { + /* + * Consider these unrecoverable errors, continuing execution + * might crash the interpreter. + */ + return -1; + } + PyErr_Clear(); + } + } if (NPY_UNLIKELY(*flags & DISCOVER_TUPLES_AS_ELEMENTS) && PyTuple_Check(obj)) { is_sequence = NPY_FALSE; } if (curr_dims == max_dims || !is_sequence) { /* Clear any PySequence_Size error which would corrupts further calls */ - PyErr_Clear(); max_dims = handle_scalar( obj, curr_dims, &max_dims, out_descr, out_shape, fixed_DType, flags, NULL); diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index f6031e370..58571b678 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -2124,7 +2124,7 @@ PyArray_FromInterface(PyObject *origin) if (iface == NULL) { if (PyErr_Occurred()) { - PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */ + return NULL; } return Py_NotImplemented; } @@ -2392,7 +2392,7 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context) array_meth = PyArray_LookupSpecial_OnInstance(op, "__array__"); if (array_meth == NULL) { if (PyErr_Occurred()) { - PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */ + return NULL; } return Py_NotImplemented; } diff --git a/numpy/core/src/multiarray/einsum_sumprod.c.src b/numpy/core/src/multiarray/einsum_sumprod.c.src index caba0e00a..86d5b82fc 100644 --- a/numpy/core/src/multiarray/einsum_sumprod.c.src +++ b/numpy/core/src/multiarray/einsum_sumprod.c.src @@ -589,7 +589,7 @@ finish_after_unrolled_loop: goto finish_after_unrolled_loop; } -static void +static NPY_GCC_OPT_3 void @name@_sum_of_products_contig_contig_outstride0_two(int nop, char **dataptr, npy_intp const *NPY_UNUSED(strides), npy_intp count) { @@ -597,156 +597,60 @@ static void @type@ *data1 = (@type@ *)dataptr[1]; @temptype@ accum = 0; -#if EINSUM_USE_SSE1 && @float32@ - __m128 a, accum_sse = _mm_setzero_ps(); -#elif EINSUM_USE_SSE2 && @float64@ - __m128d a, accum_sse = _mm_setzero_pd(); -#endif - NPY_EINSUM_DBG_PRINT1("@name@_sum_of_products_contig_contig_outstride0_two (%d)\n", (int)count); - -/* This is placed before the main loop to make small counts faster */ -finish_after_unrolled_loop: - switch (count) { -/**begin repeat2 - * #i = 6, 5, 4, 3, 2, 1, 0# - */ - case @i@+1: - accum += @from@(data0[@i@]) * @from@(data1[@i@]); -/**end repeat2**/ - case 0: - *(@type@ *)dataptr[2] = @to@(@from@(*(@type@ *)dataptr[2]) + accum); - return; - } - -#if EINSUM_USE_SSE1 && @float32@ +#if @NPYV_CHK@ // NPYV check for @type@ /* Use aligned instructions if possible */ - if (EINSUM_IS_SSE_ALIGNED(data0) && EINSUM_IS_SSE_ALIGNED(data1)) { - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - - _mm_prefetch(data0 + 512, _MM_HINT_T0); - _mm_prefetch(data1 + 512, _MM_HINT_T0); + const int is_aligned = EINSUM_IS_ALIGNED(data0) && EINSUM_IS_ALIGNED(data1); + const int vstep = npyv_nlanes_@sfx@; + npyv_@sfx@ vaccum = npyv_zero_@sfx@(); -/**begin repeat2 - * #i = 0, 4# - */ - /* - * NOTE: This accumulation changes the order, so will likely - * produce slightly different results. + /**begin repeat2 + * #cond = if(is_aligned), else# + * #ld = loada, load# + * #st = storea, store# + */ + @cond@ { + const npy_intp vstepx4 = vstep * 4; + for (; count >= vstepx4; count -= vstepx4, data0 += vstepx4, data1 += vstepx4) { + /**begin repeat3 + * #i = 0, 1, 2, 3# */ - a = _mm_mul_ps(_mm_load_ps(data0+@i@), _mm_load_ps(data1+@i@)); - accum_sse = _mm_add_ps(accum_sse, a); -/**end repeat2**/ - data0 += 8; - data1 += 8; + npyv_@sfx@ a@i@ = npyv_@ld@_@sfx@(data0 + vstep * @i@); + npyv_@sfx@ b@i@ = npyv_@ld@_@sfx@(data1 + vstep * @i@); + /**end repeat3**/ + npyv_@sfx@ ab3 = npyv_muladd_@sfx@(a3, b3, vaccum); + npyv_@sfx@ ab2 = npyv_muladd_@sfx@(a2, b2, ab3); + npyv_@sfx@ ab1 = npyv_muladd_@sfx@(a1, b1, ab2); + vaccum = npyv_muladd_@sfx@(a0, b0, ab1); } - - /* Add the four SSE values and put in accum */ - a = _mm_shuffle_ps(accum_sse, accum_sse, _MM_SHUFFLE(2,3,0,1)); - accum_sse = _mm_add_ps(a, accum_sse); - a = _mm_shuffle_ps(accum_sse, accum_sse, _MM_SHUFFLE(1,0,3,2)); - accum_sse = _mm_add_ps(a, accum_sse); - _mm_store_ss(&accum, accum_sse); - - /* Finish off the loop */ - goto finish_after_unrolled_loop; } -#elif EINSUM_USE_SSE2 && @float64@ - /* Use aligned instructions if possible */ - if (EINSUM_IS_SSE_ALIGNED(data0) && EINSUM_IS_SSE_ALIGNED(data1)) { - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - - _mm_prefetch(data0 + 512, _MM_HINT_T0); - _mm_prefetch(data1 + 512, _MM_HINT_T0); - -/**begin repeat2 - * #i = 0, 2, 4, 6# - */ - /* - * NOTE: This accumulation changes the order, so will likely - * produce slightly different results. - */ - a = _mm_mul_pd(_mm_load_pd(data0+@i@), _mm_load_pd(data1+@i@)); - accum_sse = _mm_add_pd(accum_sse, a); -/**end repeat2**/ - data0 += 8; - data1 += 8; - } - - /* Add the two SSE2 values and put in accum */ - a = _mm_shuffle_pd(accum_sse, accum_sse, _MM_SHUFFLE2(0,1)); - accum_sse = _mm_add_pd(a, accum_sse); - _mm_store_sd(&accum, accum_sse); - - /* Finish off the loop */ - goto finish_after_unrolled_loop; + /**end repeat2**/ + for (; count > 0; count -= vstep, data0 += vstep, data1 += vstep) { + npyv_@sfx@ a = npyv_load_tillz_@sfx@(data0, count); + npyv_@sfx@ b = npyv_load_tillz_@sfx@(data1, count); + vaccum = npyv_muladd_@sfx@(a, b, vaccum); } -#endif - - /* Unroll the loop by 8 */ - while (count >= 8) { - count -= 8; - -#if EINSUM_USE_SSE1 && @float32@ - _mm_prefetch(data0 + 512, _MM_HINT_T0); - _mm_prefetch(data1 + 512, _MM_HINT_T0); - -/**begin repeat2 - * #i = 0, 4# - */ - /* - * NOTE: This accumulation changes the order, so will likely - * produce slightly different results. - */ - a = _mm_mul_ps(_mm_loadu_ps(data0+@i@), _mm_loadu_ps(data1+@i@)); - accum_sse = _mm_add_ps(accum_sse, a); -/**end repeat2**/ -#elif EINSUM_USE_SSE2 && @float64@ - _mm_prefetch(data0 + 512, _MM_HINT_T0); - _mm_prefetch(data1 + 512, _MM_HINT_T0); - -/**begin repeat2 - * #i = 0, 2, 4, 6# - */ - /* - * NOTE: This accumulation changes the order, so will likely - * produce slightly different results. - */ - a = _mm_mul_pd(_mm_loadu_pd(data0+@i@), _mm_loadu_pd(data1+@i@)); - accum_sse = _mm_add_pd(accum_sse, a); -/**end repeat2**/ + accum = npyv_sum_@sfx@(vaccum); + npyv_cleanup(); #else -/**begin repeat2 - * #i = 0, 1, 2, 3, 4, 5, 6, 7# - */ - accum += @from@(data0[@i@]) * @from@(data1[@i@]); -/**end repeat2**/ -#endif - data0 += 8; - data1 += 8; +#ifndef NPY_DISABLE_OPTIMIZATION + for (; count >= 4; count -= 4, data0 += 4, data1 += 4) { + /**begin repeat2 + * #i = 0, 1, 2, 3# + */ + const @type@ ab@i@ = @from@(data0[@i@]) * @from@(data1[@i@]); + /**end repeat2**/ + accum += ab0 + ab1 + ab2 + ab3; } - -#if EINSUM_USE_SSE1 && @float32@ - /* Add the four SSE values and put in accum */ - a = _mm_shuffle_ps(accum_sse, accum_sse, _MM_SHUFFLE(2,3,0,1)); - accum_sse = _mm_add_ps(a, accum_sse); - a = _mm_shuffle_ps(accum_sse, accum_sse, _MM_SHUFFLE(1,0,3,2)); - accum_sse = _mm_add_ps(a, accum_sse); - _mm_store_ss(&accum, accum_sse); -#elif EINSUM_USE_SSE2 && @float64@ - /* Add the two SSE2 values and put in accum */ - a = _mm_shuffle_pd(accum_sse, accum_sse, _MM_SHUFFLE2(0,1)); - accum_sse = _mm_add_pd(a, accum_sse); - _mm_store_sd(&accum, accum_sse); -#endif - - /* Finish off the loop */ - goto finish_after_unrolled_loop; +#endif // !NPY_DISABLE_OPTIMIZATION + for (; count > 0; --count, ++data0, ++data1) { + const @type@ a = @from@(*data0); + const @type@ b = @from@(*data1); + accum += a * b; + } +#endif // NPYV check for @type@ + *(@type@ *)dataptr[2] = @to@(@from@(*(@type@ *)dataptr[2]) + accum); } static void diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 32c5ac0dc..870b633ed 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -4085,6 +4085,42 @@ normalize_axis_index(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds) } +static PyObject * +_reload_guard(PyObject *NPY_UNUSED(self)) { + static int initialized = 0; + +#if !defined(PYPY_VERSION) + if (PyThreadState_Get()->interp != PyInterpreterState_Main()) { + if (PyErr_WarnEx(PyExc_UserWarning, + "NumPy was imported from a Python sub-interpreter but " + "NumPy does not properly support sub-interpreters. " + "This will likely work for most users but might cause hard to " + "track down issues or subtle bugs. " + "A common user of the rare sub-interpreter feature is wsgi " + "which also allows single-interpreter mode.\n" + "Improvements in the case of bugs are welcome, but is not " + "on the NumPy roadmap, and full support may require " + "significant effort to achieve.", 2) < 0) { + return NULL; + } + /* No need to give the other warning in a sub-interpreter as well... */ + initialized = 1; + Py_RETURN_NONE; + } +#endif + if (initialized) { + if (PyErr_WarnEx(PyExc_UserWarning, + "The NumPy module was reloaded (imported a second time). " + "This can in some cases result in small but subtle issues " + "and is discouraged.", 2) < 0) { + return NULL; + } + } + initialized = 1; + Py_RETURN_NONE; +} + + static struct PyMethodDef array_module_methods[] = { {"_get_implementing_args", (PyCFunction)array__get_implementing_args, @@ -4276,6 +4312,9 @@ static struct PyMethodDef array_module_methods[] = { METH_VARARGS, NULL}, {"_set_madvise_hugepage", (PyCFunction)_set_madvise_hugepage, METH_O, NULL}, + {"_reload_guard", (PyCFunction)_reload_guard, + METH_NOARGS, + "Give a warning on reload and big warning in sub-interpreters."}, {NULL, NULL, 0, NULL} /* sentinel */ }; diff --git a/numpy/core/tests/test_array_coercion.py b/numpy/core/tests/test_array_coercion.py index 78def9360..b966ee7b0 100644 --- a/numpy/core/tests/test_array_coercion.py +++ b/numpy/core/tests/test_array_coercion.py @@ -689,3 +689,33 @@ class TestArrayLikes: np.array(arr) with pytest.raises(MemoryError): np.array([arr]) + + @pytest.mark.parametrize("attribute", + ["__array_interface__", "__array__", "__array_struct__"]) + def test_bad_array_like_attributes(self, attribute): + # Check that errors during attribute retrieval are raised unless + # they are Attribute errors. + + class BadInterface: + def __getattr__(self, attr): + if attr == attribute: + raise RuntimeError + super().__getattr__(attr) + + with pytest.raises(RuntimeError): + np.array(BadInterface()) + + @pytest.mark.parametrize("error", [RecursionError, MemoryError]) + def test_bad_array_like_bad_length(self, error): + # RecursionError and MemoryError are considered "critical" in + # sequences. We could expand this more generally though. (NumPy 1.20) + class BadSequence: + def __len__(self): + raise error + def __getitem__(self): + # must have getitem to be a Sequence + return 1 + + with pytest.raises(error): + np.array(BadSequence()) + diff --git a/numpy/fft/_pocketfft.py b/numpy/fft/_pocketfft.py index 83ac86036..2066b95ea 100644 --- a/numpy/fft/_pocketfft.py +++ b/numpy/fft/_pocketfft.py @@ -1242,6 +1242,15 @@ def rfft2(a, s=None, axes=(-2, -1), norm=None): This is really just `rfftn` with different default behavior. For more details see `rfftn`. + Examples + -------- + >>> a = np.mgrid[:5, :5][0] + >>> np.fft.rfft2(a) + array([[ 50. +0.j , 0. +0.j , 0. +0.j ], + [-12.5+17.20477401j, 0. +0.j , 0. +0.j ], + [-12.5 +4.0614962j , 0. +0.j , 0. +0.j ], + [-12.5 -4.0614962j , 0. +0.j , 0. +0.j ], + [-12.5-17.20477401j, 0. +0.j , 0. +0.j ]]) """ return rfftn(a, s, axes, norm) @@ -1399,5 +1408,15 @@ def irfft2(a, s=None, axes=(-2, -1), norm=None): This is really `irfftn` with different defaults. For more details see `irfftn`. + Examples + -------- + >>> a = np.mgrid[:5, :5][0] + >>> A = np.fft.rfft2(a) + >>> np.fft.irfft2(A, s=a.shape) + array([[0., 0., 0., 0., 0.], + [1., 1., 1., 1., 1.], + [2., 2., 2., 2., 2.], + [3., 3., 3., 3., 3.], + [4., 4., 4., 4., 4.]]) """ return irfftn(a, s, axes, norm) diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index af8e28e42..efebb5fb7 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -539,10 +539,11 @@ def _savez_dispatcher(file, *args, **kwds): def savez(file, *args, **kwds): """Save several arrays into a single file in uncompressed ``.npz`` format. - If arguments are passed in with no keywords, the corresponding variable - names, in the ``.npz`` file, are 'arr_0', 'arr_1', etc. If keyword - arguments are given, the corresponding variable names, in the ``.npz`` - file will match the keyword names. + Provide arrays as keyword arguments to store them under the + corresponding name in the output file: ``savez(fn, x=x, y=y)``. + + If arrays are specified as positional arguments, i.e., ``savez(fn, + x, y)``, their names will be `arr_0`, `arr_1`, etc. Parameters ---------- @@ -552,13 +553,12 @@ def savez(file, *args, **kwds): ``.npz`` extension will be appended to the filename if it is not already there. args : Arguments, optional - Arrays to save to the file. Since it is not possible for Python to - know the names of the arrays outside `savez`, the arrays will be saved - with names "arr_0", "arr_1", and so on. These arguments can be any - expression. + Arrays to save to the file. Please use keyword arguments (see + `kwds` below) to assign names to arrays. Arrays specified as + args will be named "arr_0", "arr_1", and so on. kwds : Keyword arguments, optional - Arrays to save to the file. Arrays will be saved in the file with the - keyword names. + Arrays to save to the file. Each array will be saved to the + output file with its corresponding keyword name. Returns ------- @@ -613,6 +613,7 @@ def savez(file, *args, **kwds): ['x', 'y'] >>> npzfile['x'] array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + """ _savez(file, args, kwds, False) @@ -627,9 +628,11 @@ def savez_compressed(file, *args, **kwds): """ Save several arrays into a single file in compressed ``.npz`` format. - If keyword arguments are given, then filenames are taken from the keywords. - If arguments are passed in with no keywords, then stored filenames are - arr_0, arr_1, etc. + Provide arrays as keyword arguments to store them under the + corresponding name in the output file: ``savez(fn, x=x, y=y)``. + + If arrays are specified as positional arguments, i.e., ``savez(fn, + x, y)``, their names will be `arr_0`, `arr_1`, etc. Parameters ---------- @@ -639,13 +642,12 @@ def savez_compressed(file, *args, **kwds): ``.npz`` extension will be appended to the filename if it is not already there. args : Arguments, optional - Arrays to save to the file. Since it is not possible for Python to - know the names of the arrays outside `savez`, the arrays will be saved - with names "arr_0", "arr_1", and so on. These arguments can be any - expression. + Arrays to save to the file. Please use keyword arguments (see + `kwds` below) to assign names to arrays. Arrays specified as + args will be named "arr_0", "arr_1", and so on. kwds : Keyword arguments, optional - Arrays to save to the file. Arrays will be saved in the file with the - keyword names. + Arrays to save to the file. Each array will be saved to the + output file with its corresponding keyword name. Returns ------- diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx index 7ffa36775..e00bc4d98 100644 --- a/numpy/random/_generator.pyx +++ b/numpy/random/_generator.pyx @@ -859,7 +859,8 @@ cdef class Generator: greater than or equal to low. The default value is 0. high : float or array_like of floats Upper boundary of the output interval. All values generated will be - less than high. The default value is 1.0. + less than high. high - low must be non-negative. The default value + is 1.0. size : int or tuple of ints, optional Output shape. If the given shape is, e.g., ``(m, n, k)``, then ``m * n * k`` samples are drawn. If size is ``None`` (default), @@ -885,10 +886,6 @@ cdef class Generator: anywhere within the interval ``[a, b)``, and zero elsewhere. When ``high`` == ``low``, values of ``low`` will be returned. - If ``high`` < ``low``, the results are officially undefined - and may eventually raise an error, i.e. do not rely on this - function to behave when passed arguments satisfying that - inequality condition. Examples -------- @@ -914,7 +911,7 @@ cdef class Generator: """ cdef bint is_scalar = True cdef np.ndarray alow, ahigh, arange - cdef double _low, _high, range + cdef double _low, _high, rng cdef object temp alow = <np.ndarray>np.PyArray_FROM_OTF(low, np.NPY_DOUBLE, np.NPY_ALIGNED) @@ -923,13 +920,13 @@ cdef class Generator: if np.PyArray_NDIM(alow) == np.PyArray_NDIM(ahigh) == 0: _low = PyFloat_AsDouble(low) _high = PyFloat_AsDouble(high) - range = _high - _low - if not np.isfinite(range): - raise OverflowError('Range exceeds valid bounds') + rng = _high - _low + if not np.isfinite(rng): + raise OverflowError('high - low range exceeds valid bounds') return cont(&random_uniform, &self._bitgen, size, self.lock, 2, _low, '', CONS_NONE, - range, '', CONS_NONE, + rng, 'high - low', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -943,7 +940,7 @@ cdef class Generator: raise OverflowError('Range exceeds valid bounds') return cont(&random_uniform, &self._bitgen, size, self.lock, 2, alow, '', CONS_NONE, - arange, '', CONS_NONE, + arange, 'high - low', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index b69cd38d4..c4fb5883c 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -1666,6 +1666,21 @@ class TestRandomDist: # DBL_MAX by increasing fmin a bit random.uniform(low=np.nextafter(fmin, 1), high=fmax / 1e17) + def test_uniform_zero_range(self): + func = random.uniform + result = func(1.5, 1.5) + assert_allclose(result, 1.5) + result = func([0.0, np.pi], [0.0, np.pi]) + assert_allclose(result, [0.0, np.pi]) + result = func([[2145.12], [2145.12]], [2145.12, 2145.12]) + assert_allclose(result, 2145.12 + np.zeros((2, 2))) + + def test_uniform_neg_range(self): + func = random.uniform + assert_raises(ValueError, func, 2, 1) + assert_raises(ValueError, func, [1, 2], [1, 1]) + assert_raises(ValueError, func, [[0, 1],[2, 3]], 2) + def test_scalar_exception_propagation(self): # Tests that exceptions are correctly propagated in distributions # when called with objects that throw exceptions when converted to diff --git a/numpy/tests/test_reloading.py b/numpy/tests/test_reloading.py index 61ae91b00..5c4309f4a 100644 --- a/numpy/tests/test_reloading.py +++ b/numpy/tests/test_reloading.py @@ -1,4 +1,4 @@ -from numpy.testing import assert_raises, assert_, assert_equal +from numpy.testing import assert_raises, assert_warns, assert_, assert_equal from numpy.compat import pickle import sys @@ -16,13 +16,15 @@ def test_numpy_reloading(): VisibleDeprecationWarning = np.VisibleDeprecationWarning ModuleDeprecationWarning = np.ModuleDeprecationWarning - reload(np) + with assert_warns(UserWarning): + reload(np) assert_(_NoValue is np._NoValue) assert_(ModuleDeprecationWarning is np.ModuleDeprecationWarning) assert_(VisibleDeprecationWarning is np.VisibleDeprecationWarning) assert_raises(RuntimeError, reload, numpy._globals) - reload(np) + with assert_warns(UserWarning): + reload(np) assert_(_NoValue is np._NoValue) assert_(ModuleDeprecationWarning is np.ModuleDeprecationWarning) assert_(VisibleDeprecationWarning is np.VisibleDeprecationWarning) @@ -45,13 +47,15 @@ def test_full_reimport(): # This is generally unsafe, especially, since we also reload the C-modules. code = textwrap.dedent(r""" import sys + from pytest import warns import numpy as np for k in list(sys.modules.keys()): if "numpy" in k: del sys.modules[k] - import numpy as np + with warns(UserWarning): + import numpy as np """) p = subprocess.run([sys.executable, '-c', code]) - assert p.returncode == 0 + diff --git a/pytest.ini b/pytest.ini index 149af04b8..dfad538c2 100644 --- a/pytest.ini +++ b/pytest.ini @@ -14,4 +14,5 @@ filterwarnings = # Matrix PendingDeprecationWarning. ignore:the matrix subclass is not ignore:Importing from numpy.matlib is - +# pytest warning when using PYTHONOPTIMIZE + ignore:assertions not in test modules or plugins:pytest.PytestConfigWarning diff --git a/runtests.py b/runtests.py index bad93f53a..4c9493a35 100755 --- a/runtests.py +++ b/runtests.py @@ -524,6 +524,7 @@ def asv_compare_config(bench_path, args, h_commits): is_cached = asv_substitute_config(conf_path, nconf_path, numpy_build_options = ' '.join([f'\\"{v}\\"' for v in build]), + numpy_global_options= ' '.join([f'--global-option=\\"{v}\\"' for v in ["build"] + build]) ) if not is_cached: asv_clear_cache(bench_path, h_commits) diff --git a/test_requirements.txt b/test_requirements.txt index 5166ada16..e3fc9ccc6 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,8 +1,8 @@ cython==0.29.21 -wheel<=0.35.1 +wheel<0.36.3 setuptools<49.2.0 -hypothesis==5.41.5 -pytest==6.0.2 +hypothesis==5.43.3 +pytest==6.2.0 pytz==2020.4 pytest-cov==2.10.1 pickle5; python_version == '3.7' and platform_python_implementation != 'PyPy' |