summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--azure-pipelines.yml10
-rw-r--r--doc/HOWTO_RELEASE.rst.txt23
-rw-r--r--doc/neps/_static/casting_flow.svg2212
-rw-r--r--doc/neps/_static/dtype_hierarchy.svg935
-rw-r--r--doc/neps/nep-0029-deprecation_policy.rst2
-rw-r--r--doc/neps/nep-0042-new-dtypes.rst1330
-rw-r--r--doc/neps/nep-0045-c_style_guide.rst11
-rw-r--r--doc/neps/roadmap.rst101
-rw-r--r--doc/release/upcoming_changes/16056.deprecation.rst13
-rw-r--r--doc/release/upcoming_changes/16515.new_feature.rst8
-rw-r--r--doc/release/upcoming_changes/16519.improvement.rst4
-rw-r--r--doc/release/upcoming_changes/16554.compatibility.rst10
-rw-r--r--doc/release/upcoming_changes/16554.deprecation.rst8
-rw-r--r--doc/release/upcoming_changes/16554.expired.rst5
-rw-r--r--doc/source/conf.py3
-rw-r--r--doc/source/dev/gitwash/git_links.inc4
-rw-r--r--doc/source/dev/governance/governance.rst3
-rw-r--r--doc/source/dev/howto-docs.rst265
-rw-r--r--doc/source/dev/index.rst9
-rw-r--r--doc/source/reference/arrays.classes.rst2
-rw-r--r--doc/source/reference/global_state.rst4
-rw-r--r--doc/source/reference/random/new-or-different.rst4
-rw-r--r--doc/source/reference/ufuncs.rst2
-rw-r--r--doc/source/release/1.19.0-notes.rst43
-rw-r--r--doc/source/release/1.5.0-notes.rst4
-rw-r--r--doc/source/user/absolute_beginners.rst6
-rw-r--r--doc/source/user/building.rst12
-rw-r--r--doc/source/user/quickstart.rst10
-rw-r--r--numpy/__init__.py9
-rw-r--r--numpy/__init__.pyi1062
-rw-r--r--numpy/core/_add_newdocs.py49
-rw-r--r--numpy/core/_dtype.py6
-rw-r--r--numpy/core/_internal.pyi18
-rw-r--r--numpy/core/_type_aliases.py59
-rw-r--r--numpy/core/einsumfunc.py11
-rw-r--r--numpy/core/function_base.py32
-rw-r--r--numpy/core/include/numpy/npy_3kcompat.h4
-rw-r--r--numpy/core/numerictypes.py4
-rw-r--r--numpy/core/setup.py1
-rw-r--r--numpy/core/src/common/npy_cpu_features.c.src38
-rw-r--r--numpy/core/src/common/npy_cpuinfo_parser.h262
-rw-r--r--numpy/core/src/multiarray/conversion_utils.c48
-rw-r--r--numpy/core/src/multiarray/descriptor.c6
-rw-r--r--numpy/core/src/multiarray/mapping.c4
-rw-r--r--numpy/core/src/umath/simd.inc.src8
-rw-r--r--numpy/core/tests/test_conversion_utils.py30
-rw-r--r--numpy/core/tests/test_deprecations.py35
-rw-r--r--numpy/core/tests/test_dtype.py15
-rw-r--r--numpy/core/tests/test_einsum.py39
-rw-r--r--numpy/core/tests/test_function_base.py36
-rw-r--r--numpy/core/tests/test_multiarray.py72
-rw-r--r--numpy/core/tests/test_regression.py7
-rw-r--r--numpy/core/tests/test_umath.py10
-rw-r--r--numpy/core/tests/test_umath_accuracy.py6
-rw-r--r--numpy/doc/dispatch.py2
-rw-r--r--numpy/f2py/cb_rules.py339
-rw-r--r--numpy/f2py/cfuncs.py15
-rwxr-xr-xnumpy/f2py/rules.py85
-rw-r--r--numpy/f2py/src/fortranobject.c62
-rw-r--r--numpy/f2py/src/fortranobject.h3
-rw-r--r--numpy/f2py/tests/test_callback.py50
-rw-r--r--numpy/lib/format.py4
-rw-r--r--numpy/lib/function_base.py5
-rw-r--r--numpy/lib/mixins.py2
-rw-r--r--numpy/ma/core.py12
-rw-r--r--numpy/ma/extras.py11
-rw-r--r--numpy/ma/tests/test_core.py34
-rw-r--r--numpy/polynomial/_polybase.py6
-rw-r--r--numpy/polynomial/chebyshev.py2
-rw-r--r--numpy/py.typed0
-rw-r--r--numpy/random/_common.pyx30
-rw-r--r--numpy/random/_generator.pyx5
-rw-r--r--numpy/random/bit_generator.pyx11
-rw-r--r--numpy/random/tests/test_generator_mt19937.py41
-rw-r--r--numpy/random/tests/test_seed_sequence.py28
-rw-r--r--numpy/setup.py2
-rw-r--r--numpy/testing/_private/nosetester.py2
-rw-r--r--numpy/testing/tests/test_utils.py33
-rw-r--r--numpy/tests/setup.py10
-rw-r--r--numpy/tests/test_typing.py142
-rw-r--r--numpy/tests/typing/fail/array_like.py22
-rw-r--r--numpy/tests/typing/fail/fromnumeric.py91
-rw-r--r--numpy/tests/typing/fail/ndarray.py11
-rw-r--r--numpy/tests/typing/fail/numerictypes.py13
-rw-r--r--numpy/tests/typing/fail/scalars.py81
-rw-r--r--numpy/tests/typing/fail/simple.py10
-rw-r--r--numpy/tests/typing/fail/ufuncs.py5
-rw-r--r--numpy/tests/typing/fail/warnings_and_errors.py7
-rw-r--r--numpy/tests/typing/mypy.ini8
-rw-r--r--numpy/tests/typing/pass/array_like.py44
-rw-r--r--numpy/tests/typing/pass/dtype.py3
-rw-r--r--numpy/tests/typing/pass/fromnumeric.py116
-rw-r--r--numpy/tests/typing/pass/ndarray_conversion.py94
-rw-r--r--numpy/tests/typing/pass/ndarray_shape_manipulation.py47
-rw-r--r--numpy/tests/typing/pass/numerictypes.py29
-rw-r--r--numpy/tests/typing/pass/scalars.py92
-rw-r--r--numpy/tests/typing/pass/simple.py176
-rw-r--r--numpy/tests/typing/pass/simple_py3.py6
-rw-r--r--numpy/tests/typing/pass/ufuncs.py11
-rw-r--r--numpy/tests/typing/pass/warnings_and_errors.py7
-rw-r--r--numpy/tests/typing/reveal/constants.py44
-rw-r--r--numpy/tests/typing/reveal/fromnumeric.py135
-rw-r--r--numpy/tests/typing/reveal/ndarray_conversion.py54
-rw-r--r--numpy/tests/typing/reveal/ndarray_shape_manipulation.py35
-rw-r--r--numpy/tests/typing/reveal/numerictypes.py18
-rw-r--r--numpy/tests/typing/reveal/scalars.py30
-rw-r--r--numpy/tests/typing/reveal/warnings_and_errors.py10
-rw-r--r--numpy/typing.pyi64
-rw-r--r--site.cfg.example8
-rw-r--r--test_requirements.txt8
111 files changed, 8427 insertions, 703 deletions
diff --git a/.gitignore b/.gitignore
index a203abd5b..302968a14 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,7 @@ GRTAGS
GSYMS
GTAGS
.cache
+.mypy_cache/
# Compiled source #
###################
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index ea2b414b0..397605765 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -195,16 +195,6 @@ stages:
strategy:
maxParallel: 6
matrix:
- Python36-32bit-fast:
- PYTHON_VERSION: '3.6'
- PYTHON_ARCH: 'x86'
- TEST_MODE: fast
- BITS: 32
- Python37-32bit-fast:
- PYTHON_VERSION: '3.7'
- PYTHON_ARCH: 'x86'
- TEST_MODE: fast
- BITS: 32
Python38-32bit-fast:
PYTHON_VERSION: '3.8'
PYTHON_ARCH: 'x86'
diff --git a/doc/HOWTO_RELEASE.rst.txt b/doc/HOWTO_RELEASE.rst.txt
index 6af8d9ca6..bd15f7f50 100644
--- a/doc/HOWTO_RELEASE.rst.txt
+++ b/doc/HOWTO_RELEASE.rst.txt
@@ -19,18 +19,11 @@ Source tree
NumPy Docs
----------
- https://github.com/numpy/numpy/blob/master/doc/HOWTO_RELEASE.rst.txt
-- http://projects.scipy.org/numpy/wiki/MicrosoftToolchainSupport (dead link)
SciPy.org wiki
--------------
- https://www.scipy.org/Installing_SciPy and links on that page.
-- http://new.scipy.org/building/windows.html (dead link)
-
-
-Doc wiki
---------
-- http://docs.scipy.org/numpy/docs/numpy-docs/user/install.rst/ (dead link)
Release Scripts
@@ -40,16 +33,17 @@ Release Scripts
Supported platforms and versions
================================
-`NEP 29`_ outlines which Python versions are supported; For the first half of
-2020, this will be Python >= 3.6. We test NumPy against all these versions
-every time we merge code to master. Binary installers may be available for a
-subset of these versions (see below).
+:ref:`NEP 29 <NEP29>` outlines which Python versions
+are supported; For the first half of 2020, this will be Python >= 3.6. We test
+NumPy against all these versions every time we merge code to master. Binary
+installers may be available for a subset of these versions (see below).
OS X
----
-OS X versions >= 10.9 are supported, for Python version support see `NEP 29`_.
-We build binary wheels for OSX that are compatible with Python.org Python,
-system Python, homebrew and macports - see this `OSX wheel building summary
+OS X versions >= 10.9 are supported, for Python version support see
+:ref:`NEP 29 <NEP29>`. We build binary wheels for
+OSX that are compatible with Python.org Python, system Python, homebrew and
+macports - see this `OSX wheel building summary
<https://github.com/MacPython/wiki/wiki/Spinning-wheels>`_ for details.
@@ -95,7 +89,6 @@ You will need Cython for building the binaries. Cython compiles the ``.pyx``
files in the NumPy distribution to ``.c`` files.
.. _mingw-w64 toolchain : https://mingwpy.github.io
-.. _NEP 29 : https://numpy.org/neps/nep-0029-deprecation_policy.html
OpenBLAS
------------
diff --git a/doc/neps/_static/casting_flow.svg b/doc/neps/_static/casting_flow.svg
new file mode 100644
index 000000000..8b4b96477
--- /dev/null
+++ b/doc/neps/_static/casting_flow.svg
@@ -0,0 +1,2212 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="908pt"
+ height="444pt"
+ viewBox="0 0 908 444"
+ version="1.1"
+ id="svg2577"
+ sodipodi:docname="casting_flow.svg"
+ inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)">
+ <metadata
+ id="metadata2581">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:document-rotation="0"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2560"
+ inkscape:window-height="1376"
+ id="namedview2579"
+ showgrid="false"
+ inkscape:zoom="1.1348363"
+ inkscape:cx="754.6365"
+ inkscape:cy="382.73477"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="surface392452" />
+ <defs
+ id="defs1910">
+ <g
+ id="g1908">
+ <symbol
+ overflow="visible"
+ id="glyph0-0">
+ <path
+ style="stroke:none;"
+ d="M 0.640625 2.265625 L 0.640625 -9.015625 L 7.03125 -9.015625 L 7.03125 2.265625 Z M 1.359375 1.546875 L 6.328125 1.546875 L 6.328125 -8.296875 L 1.359375 -8.296875 Z M 1.359375 1.546875 "
+ id="path1734" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-1">
+ <path
+ style="stroke:none;"
+ d="M 8.234375 -8.609375 L 8.234375 -7.28125 C 7.816406 -7.675781 7.363281 -7.96875 6.875 -8.15625 C 6.394531 -8.351562 5.882812 -8.453125 5.34375 -8.453125 C 4.28125 -8.453125 3.460938 -8.125 2.890625 -7.46875 C 2.328125 -6.820312 2.046875 -5.882812 2.046875 -4.65625 C 2.046875 -3.425781 2.328125 -2.484375 2.890625 -1.828125 C 3.460938 -1.179688 4.28125 -0.859375 5.34375 -0.859375 C 5.882812 -0.859375 6.394531 -0.953125 6.875 -1.140625 C 7.363281 -1.335938 7.816406 -1.632812 8.234375 -2.03125 L 8.234375 -0.71875 C 7.796875 -0.414062 7.328125 -0.1875 6.828125 -0.03125 C 6.335938 0.113281 5.820312 0.1875 5.28125 0.1875 C 3.863281 0.1875 2.75 -0.242188 1.9375 -1.109375 C 1.125 -1.972656 0.71875 -3.15625 0.71875 -4.65625 C 0.71875 -6.15625 1.125 -7.335938 1.9375 -8.203125 C 2.75 -9.066406 3.863281 -9.5 5.28125 -9.5 C 5.832031 -9.5 6.351562 -9.421875 6.84375 -9.265625 C 7.34375 -9.117188 7.804688 -8.898438 8.234375 -8.609375 Z M 8.234375 -8.609375 "
+ id="path1737" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-2">
+ <path
+ style="stroke:none;"
+ d="M 4.390625 -3.515625 C 3.460938 -3.515625 2.816406 -3.40625 2.453125 -3.1875 C 2.097656 -2.976562 1.921875 -2.617188 1.921875 -2.109375 C 1.921875 -1.703125 2.050781 -1.378906 2.3125 -1.140625 C 2.582031 -0.898438 2.953125 -0.78125 3.421875 -0.78125 C 4.054688 -0.78125 4.566406 -1.003906 4.953125 -1.453125 C 5.335938 -1.910156 5.53125 -2.515625 5.53125 -3.265625 L 5.53125 -3.515625 Z M 6.671875 -4 L 6.671875 0 L 5.53125 0 L 5.53125 -1.0625 C 5.269531 -0.632812 4.941406 -0.316406 4.546875 -0.109375 C 4.160156 0.0859375 3.679688 0.1875 3.109375 0.1875 C 2.390625 0.1875 1.816406 -0.015625 1.390625 -0.421875 C 0.972656 -0.828125 0.765625 -1.363281 0.765625 -2.03125 C 0.765625 -2.820312 1.023438 -3.414062 1.546875 -3.8125 C 2.078125 -4.21875 2.867188 -4.421875 3.921875 -4.421875 L 5.53125 -4.421875 L 5.53125 -4.53125 C 5.53125 -5.0625 5.351562 -5.46875 5 -5.75 C 4.65625 -6.039062 4.171875 -6.1875 3.546875 -6.1875 C 3.140625 -6.1875 2.75 -6.140625 2.375 -6.046875 C 2 -5.953125 1.632812 -5.8125 1.28125 -5.625 L 1.28125 -6.671875 C 1.695312 -6.835938 2.101562 -6.960938 2.5 -7.046875 C 2.894531 -7.128906 3.28125 -7.171875 3.65625 -7.171875 C 4.675781 -7.171875 5.429688 -6.90625 5.921875 -6.375 C 6.421875 -5.851562 6.671875 -5.0625 6.671875 -4 Z M 6.671875 -4 "
+ id="path1740" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-3">
+ <path
+ style="stroke:none;"
+ d="M 5.671875 -6.796875 L 5.671875 -5.703125 C 5.347656 -5.867188 5.007812 -5.992188 4.65625 -6.078125 C 4.300781 -6.160156 3.9375 -6.203125 3.5625 -6.203125 C 3 -6.203125 2.570312 -6.113281 2.28125 -5.9375 C 2 -5.769531 1.859375 -5.507812 1.859375 -5.15625 C 1.859375 -4.882812 1.957031 -4.671875 2.15625 -4.515625 C 2.363281 -4.367188 2.773438 -4.226562 3.390625 -4.09375 L 3.78125 -4 C 4.601562 -3.832031 5.1875 -3.585938 5.53125 -3.265625 C 5.875 -2.941406 6.046875 -2.5 6.046875 -1.9375 C 6.046875 -1.28125 5.785156 -0.757812 5.265625 -0.375 C 4.753906 0 4.050781 0.1875 3.15625 0.1875 C 2.78125 0.1875 2.390625 0.148438 1.984375 0.078125 C 1.578125 0.00390625 1.144531 -0.101562 0.6875 -0.25 L 0.6875 -1.4375 C 1.113281 -1.21875 1.53125 -1.050781 1.9375 -0.9375 C 2.351562 -0.832031 2.765625 -0.78125 3.171875 -0.78125 C 3.710938 -0.78125 4.128906 -0.875 4.421875 -1.0625 C 4.710938 -1.25 4.859375 -1.507812 4.859375 -1.84375 C 4.859375 -2.15625 4.753906 -2.394531 4.546875 -2.5625 C 4.335938 -2.726562 3.875 -2.890625 3.15625 -3.046875 L 2.765625 -3.140625 C 2.046875 -3.285156 1.53125 -3.515625 1.21875 -3.828125 C 0.90625 -4.140625 0.75 -4.566406 0.75 -5.109375 C 0.75 -5.765625 0.976562 -6.269531 1.4375 -6.625 C 1.90625 -6.988281 2.570312 -7.171875 3.4375 -7.171875 C 3.851562 -7.171875 4.25 -7.140625 4.625 -7.078125 C 5 -7.015625 5.347656 -6.921875 5.671875 -6.796875 Z M 5.671875 -6.796875 "
+ id="path1743" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-4">
+ <path
+ style="stroke:none;"
+ d="M 2.34375 -8.984375 L 2.34375 -7 L 4.71875 -7 L 4.71875 -6.109375 L 2.34375 -6.109375 L 2.34375 -2.3125 C 2.34375 -1.738281 2.421875 -1.367188 2.578125 -1.203125 C 2.734375 -1.046875 3.050781 -0.96875 3.53125 -0.96875 L 4.71875 -0.96875 L 4.71875 0 L 3.53125 0 C 2.644531 0 2.03125 -0.164062 1.6875 -0.5 C 1.351562 -0.832031 1.1875 -1.4375 1.1875 -2.3125 L 1.1875 -6.109375 L 0.34375 -6.109375 L 0.34375 -7 L 1.1875 -7 L 1.1875 -8.984375 Z M 2.34375 -8.984375 "
+ id="path1746" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-5">
+ <path
+ style="stroke:none;"
+ d="M 1.203125 -7 L 2.359375 -7 L 2.359375 0 L 1.203125 0 Z M 1.203125 -9.71875 L 2.359375 -9.71875 L 2.359375 -8.265625 L 1.203125 -8.265625 Z M 1.203125 -9.71875 "
+ id="path1749" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-6">
+ <path
+ style="stroke:none;"
+ d="M 7.015625 -4.21875 L 7.015625 0 L 5.875 0 L 5.875 -4.1875 C 5.875 -4.851562 5.742188 -5.347656 5.484375 -5.671875 C 5.222656 -6.003906 4.835938 -6.171875 4.328125 -6.171875 C 3.703125 -6.171875 3.207031 -5.972656 2.84375 -5.578125 C 2.488281 -5.179688 2.3125 -4.640625 2.3125 -3.953125 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.59375 -6.332031 2.914062 -6.648438 3.28125 -6.859375 C 3.65625 -7.066406 4.085938 -7.171875 4.578125 -7.171875 C 5.378906 -7.171875 5.984375 -6.921875 6.390625 -6.421875 C 6.804688 -5.921875 7.015625 -5.1875 7.015625 -4.21875 Z M 7.015625 -4.21875 "
+ id="path1752" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-7">
+ <path
+ style="stroke:none;"
+ d="M 5.8125 -3.578125 C 5.8125 -4.410156 5.640625 -5.054688 5.296875 -5.515625 C 4.953125 -5.972656 4.46875 -6.203125 3.84375 -6.203125 C 3.226562 -6.203125 2.75 -5.972656 2.40625 -5.515625 C 2.0625 -5.054688 1.890625 -4.410156 1.890625 -3.578125 C 1.890625 -2.753906 2.0625 -2.113281 2.40625 -1.65625 C 2.75 -1.195312 3.226562 -0.96875 3.84375 -0.96875 C 4.46875 -0.96875 4.953125 -1.195312 5.296875 -1.65625 C 5.640625 -2.113281 5.8125 -2.753906 5.8125 -3.578125 Z M 6.953125 -0.875 C 6.953125 0.320312 6.6875 1.207031 6.15625 1.78125 C 5.632812 2.363281 4.828125 2.65625 3.734375 2.65625 C 3.328125 2.65625 2.945312 2.625 2.59375 2.5625 C 2.238281 2.507812 1.890625 2.421875 1.546875 2.296875 L 1.546875 1.171875 C 1.890625 1.359375 2.222656 1.492188 2.546875 1.578125 C 2.878906 1.671875 3.21875 1.71875 3.5625 1.71875 C 4.3125 1.71875 4.875 1.519531 5.25 1.125 C 5.625 0.726562 5.8125 0.132812 5.8125 -0.65625 L 5.8125 -1.234375 C 5.570312 -0.816406 5.265625 -0.503906 4.890625 -0.296875 C 4.523438 -0.0976562 4.082031 0 3.5625 0 C 2.707031 0 2.015625 -0.328125 1.484375 -0.984375 C 0.960938 -1.640625 0.703125 -2.503906 0.703125 -3.578125 C 0.703125 -4.660156 0.960938 -5.53125 1.484375 -6.1875 C 2.015625 -6.84375 2.707031 -7.171875 3.5625 -7.171875 C 4.082031 -7.171875 4.523438 -7.066406 4.890625 -6.859375 C 5.265625 -6.648438 5.570312 -6.34375 5.8125 -5.9375 L 5.8125 -7 L 6.953125 -7 Z M 6.953125 -0.875 "
+ id="path1755" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-8">
+ <path
+ style="stroke:none;"
+ d="M 1.25 -9.328125 L 2.515625 -9.328125 L 2.515625 0 L 1.25 0 Z M 1.25 -9.328125 "
+ id="path1758" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-9">
+ <path
+ style="stroke:none;"
+ d="M 6.65625 -5.65625 C 6.9375 -6.164062 7.273438 -6.546875 7.671875 -6.796875 C 8.078125 -7.046875 8.550781 -7.171875 9.09375 -7.171875 C 9.820312 -7.171875 10.382812 -6.914062 10.78125 -6.40625 C 11.175781 -5.894531 11.375 -5.164062 11.375 -4.21875 L 11.375 0 L 10.21875 0 L 10.21875 -4.1875 C 10.21875 -4.851562 10.097656 -5.347656 9.859375 -5.671875 C 9.628906 -6.003906 9.269531 -6.171875 8.78125 -6.171875 C 8.1875 -6.171875 7.710938 -5.972656 7.359375 -5.578125 C 7.015625 -5.179688 6.84375 -4.640625 6.84375 -3.953125 L 6.84375 0 L 5.6875 0 L 5.6875 -4.1875 C 5.6875 -4.863281 5.566406 -5.363281 5.328125 -5.6875 C 5.097656 -6.007812 4.734375 -6.171875 4.234375 -6.171875 C 3.648438 -6.171875 3.179688 -5.96875 2.828125 -5.5625 C 2.484375 -5.164062 2.3125 -4.628906 2.3125 -3.953125 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.582031 -6.332031 2.898438 -6.648438 3.265625 -6.859375 C 3.628906 -7.066406 4.0625 -7.171875 4.5625 -7.171875 C 5.070312 -7.171875 5.503906 -7.039062 5.859375 -6.78125 C 6.222656 -6.519531 6.488281 -6.144531 6.65625 -5.65625 Z M 6.65625 -5.65625 "
+ id="path1761" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-10">
+ <path
+ style="stroke:none;"
+ d="M 2.3125 -1.046875 L 2.3125 2.65625 L 1.15625 2.65625 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.9375 C 2.5625 -6.351562 2.867188 -6.660156 3.234375 -6.859375 C 3.597656 -7.066406 4.039062 -7.171875 4.5625 -7.171875 C 5.40625 -7.171875 6.09375 -6.832031 6.625 -6.15625 C 7.15625 -5.476562 7.421875 -4.59375 7.421875 -3.5 C 7.421875 -2.394531 7.15625 -1.503906 6.625 -0.828125 C 6.09375 -0.148438 5.40625 0.1875 4.5625 0.1875 C 4.039062 0.1875 3.597656 0.0859375 3.234375 -0.109375 C 2.867188 -0.316406 2.5625 -0.628906 2.3125 -1.046875 Z M 6.234375 -3.5 C 6.234375 -4.34375 6.054688 -5.003906 5.703125 -5.484375 C 5.359375 -5.960938 4.882812 -6.203125 4.28125 -6.203125 C 3.664062 -6.203125 3.179688 -5.960938 2.828125 -5.484375 C 2.484375 -5.003906 2.3125 -4.34375 2.3125 -3.5 C 2.3125 -2.644531 2.484375 -1.976562 2.828125 -1.5 C 3.179688 -1.019531 3.664062 -0.78125 4.28125 -0.78125 C 4.882812 -0.78125 5.359375 -1.019531 5.703125 -1.5 C 6.054688 -1.976562 6.234375 -2.644531 6.234375 -3.5 Z M 6.234375 -3.5 "
+ id="path1764" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-11">
+ <path
+ style="stroke:none;"
+ d="M 1.203125 -9.71875 L 2.359375 -9.71875 L 2.359375 0 L 1.203125 0 Z M 1.203125 -9.71875 "
+ id="path1767" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-12">
+ <path
+ style="stroke:none;"
+ d="M 1.09375 -9.71875 L 3.75 -9.71875 L 3.75 -8.828125 L 2.25 -8.828125 L 2.25 0.796875 L 3.75 0.796875 L 3.75 1.6875 L 1.09375 1.6875 Z M 1.09375 -9.71875 "
+ id="path1770" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-13">
+ <path
+ style="stroke:none;"
+ d="M 2.453125 -1.0625 L 6.859375 -1.0625 L 6.859375 0 L 0.9375 0 L 0.9375 -1.0625 C 1.414062 -1.5625 2.066406 -2.226562 2.890625 -3.0625 C 3.722656 -3.894531 4.242188 -4.429688 4.453125 -4.671875 C 4.859375 -5.128906 5.140625 -5.515625 5.296875 -5.828125 C 5.460938 -6.140625 5.546875 -6.445312 5.546875 -6.75 C 5.546875 -7.25 5.367188 -7.65625 5.015625 -7.96875 C 4.671875 -8.28125 4.21875 -8.4375 3.65625 -8.4375 C 3.257812 -8.4375 2.84375 -8.363281 2.40625 -8.21875 C 1.96875 -8.082031 1.5 -7.878906 1 -7.609375 L 1 -8.875 C 1.507812 -9.082031 1.984375 -9.238281 2.421875 -9.34375 C 2.867188 -9.445312 3.273438 -9.5 3.640625 -9.5 C 4.609375 -9.5 5.378906 -9.253906 5.953125 -8.765625 C 6.523438 -8.285156 6.8125 -7.640625 6.8125 -6.828125 C 6.8125 -6.453125 6.738281 -6.09375 6.59375 -5.75 C 6.445312 -5.40625 6.1875 -5 5.8125 -4.53125 C 5.707031 -4.40625 5.375 -4.054688 4.8125 -3.484375 C 4.257812 -2.910156 3.472656 -2.101562 2.453125 -1.0625 Z M 2.453125 -1.0625 "
+ id="path1773" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-14">
+ <path
+ style="stroke:none;"
+ d="M 4.84375 -8.234375 L 1.65625 -3.25 L 4.84375 -3.25 Z M 4.5 -9.328125 L 6.09375 -9.328125 L 6.09375 -3.25 L 7.421875 -3.25 L 7.421875 -2.203125 L 6.09375 -2.203125 L 6.09375 0 L 4.84375 0 L 4.84375 -2.203125 L 0.625 -2.203125 L 0.625 -3.421875 Z M 4.5 -9.328125 "
+ id="path1776" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-15">
+ <path
+ style="stroke:none;"
+ d="M 1.5 -1.59375 L 2.8125 -1.59375 L 2.8125 -0.515625 L 1.796875 1.484375 L 0.984375 1.484375 L 1.5 -0.515625 Z M 1.5 -1.59375 "
+ id="path1779" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-16">
+ <path
+ style="stroke:none;"
+ d=""
+ id="path1782" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-17">
+ <path
+ style="stroke:none;"
+ d="M 6.84375 -9.015625 L 6.84375 -7.796875 C 6.363281 -8.023438 5.910156 -8.191406 5.484375 -8.296875 C 5.066406 -8.410156 4.660156 -8.46875 4.265625 -8.46875 C 3.578125 -8.46875 3.046875 -8.332031 2.671875 -8.0625 C 2.296875 -7.800781 2.109375 -7.425781 2.109375 -6.9375 C 2.109375 -6.519531 2.234375 -6.207031 2.484375 -6 C 2.734375 -5.789062 3.203125 -5.625 3.890625 -5.5 L 4.65625 -5.34375 C 5.59375 -5.15625 6.285156 -4.835938 6.734375 -4.390625 C 7.179688 -3.941406 7.40625 -3.335938 7.40625 -2.578125 C 7.40625 -1.671875 7.101562 -0.984375 6.5 -0.515625 C 5.894531 -0.046875 5.007812 0.1875 3.84375 0.1875 C 3.394531 0.1875 2.921875 0.132812 2.421875 0.03125 C 1.929688 -0.0703125 1.414062 -0.21875 0.875 -0.40625 L 0.875 -1.71875 C 1.394531 -1.425781 1.898438 -1.207031 2.390625 -1.0625 C 2.878906 -0.914062 3.363281 -0.84375 3.84375 -0.84375 C 4.5625 -0.84375 5.113281 -0.984375 5.5 -1.265625 C 5.894531 -1.546875 6.09375 -1.953125 6.09375 -2.484375 C 6.09375 -2.941406 5.953125 -3.296875 5.671875 -3.546875 C 5.390625 -3.804688 4.925781 -4.003906 4.28125 -4.140625 L 3.515625 -4.28125 C 2.578125 -4.46875 1.894531 -4.757812 1.46875 -5.15625 C 1.050781 -5.5625 0.84375 -6.117188 0.84375 -6.828125 C 0.84375 -7.660156 1.132812 -8.3125 1.71875 -8.78125 C 2.300781 -9.257812 3.101562 -9.5 4.125 -9.5 C 4.5625 -9.5 5.003906 -9.457031 5.453125 -9.375 C 5.910156 -9.300781 6.375 -9.179688 6.84375 -9.015625 Z M 6.84375 -9.015625 "
+ id="path1785" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-18">
+ <path
+ style="stroke:none;"
+ d="M 5.265625 -5.921875 C 5.128906 -5.992188 4.984375 -6.046875 4.828125 -6.078125 C 4.679688 -6.117188 4.519531 -6.140625 4.34375 -6.140625 C 3.6875 -6.140625 3.179688 -5.925781 2.828125 -5.5 C 2.484375 -5.082031 2.3125 -4.476562 2.3125 -3.6875 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.5625 -6.332031 2.878906 -6.648438 3.265625 -6.859375 C 3.648438 -7.066406 4.117188 -7.171875 4.671875 -7.171875 C 4.753906 -7.171875 4.84375 -7.164062 4.9375 -7.15625 C 5.03125 -7.144531 5.132812 -7.128906 5.25 -7.109375 Z M 5.265625 -5.921875 "
+ id="path1788" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-19">
+ <path
+ style="stroke:none;"
+ d="M 3.890625 -9.71875 L 3.890625 1.6875 L 1.25 1.6875 L 1.25 0.796875 L 2.734375 0.796875 L 2.734375 -8.828125 L 1.25 -8.828125 L 1.25 -9.71875 Z M 3.890625 -9.71875 "
+ id="path1791" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-20">
+ <path
+ style="stroke:none;"
+ d="M 4.0625 -8.5 C 3.414062 -8.5 2.925781 -8.175781 2.59375 -7.53125 C 2.269531 -6.894531 2.109375 -5.9375 2.109375 -4.65625 C 2.109375 -3.375 2.269531 -2.410156 2.59375 -1.765625 C 2.925781 -1.128906 3.414062 -0.8125 4.0625 -0.8125 C 4.71875 -0.8125 5.207031 -1.128906 5.53125 -1.765625 C 5.863281 -2.410156 6.03125 -3.375 6.03125 -4.65625 C 6.03125 -5.9375 5.863281 -6.894531 5.53125 -7.53125 C 5.207031 -8.175781 4.71875 -8.5 4.0625 -8.5 Z M 4.0625 -9.5 C 5.113281 -9.5 5.914062 -9.082031 6.46875 -8.25 C 7.019531 -7.425781 7.296875 -6.226562 7.296875 -4.65625 C 7.296875 -3.082031 7.019531 -1.878906 6.46875 -1.046875 C 5.914062 -0.222656 5.113281 0.1875 4.0625 0.1875 C 3.019531 0.1875 2.222656 -0.222656 1.671875 -1.046875 C 1.117188 -1.878906 0.84375 -3.082031 0.84375 -4.65625 C 0.84375 -6.226562 1.117188 -7.425781 1.671875 -8.25 C 2.222656 -9.082031 3.019531 -9.5 4.0625 -9.5 Z M 4.0625 -9.5 "
+ id="path1794" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-21">
+ <path
+ style="stroke:none;"
+ d="M 5.8125 -5.9375 L 5.8125 -9.71875 L 6.953125 -9.71875 L 6.953125 0 L 5.8125 0 L 5.8125 -1.046875 C 5.570312 -0.628906 5.265625 -0.316406 4.890625 -0.109375 C 4.523438 0.0859375 4.082031 0.1875 3.5625 0.1875 C 2.71875 0.1875 2.03125 -0.148438 1.5 -0.828125 C 0.96875 -1.503906 0.703125 -2.394531 0.703125 -3.5 C 0.703125 -4.59375 0.96875 -5.476562 1.5 -6.15625 C 2.03125 -6.832031 2.71875 -7.171875 3.5625 -7.171875 C 4.082031 -7.171875 4.523438 -7.066406 4.890625 -6.859375 C 5.265625 -6.660156 5.570312 -6.351562 5.8125 -5.9375 Z M 1.890625 -3.5 C 1.890625 -2.644531 2.0625 -1.976562 2.40625 -1.5 C 2.757812 -1.019531 3.238281 -0.78125 3.84375 -0.78125 C 4.457031 -0.78125 4.9375 -1.019531 5.28125 -1.5 C 5.632812 -1.976562 5.8125 -2.644531 5.8125 -3.5 C 5.8125 -4.34375 5.632812 -5.003906 5.28125 -5.484375 C 4.9375 -5.960938 4.457031 -6.203125 3.84375 -6.203125 C 3.238281 -6.203125 2.757812 -5.960938 2.40625 -5.484375 C 2.0625 -5.003906 1.890625 -4.34375 1.890625 -3.5 Z M 1.890625 -3.5 "
+ id="path1797" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-22">
+ <path
+ style="stroke:none;"
+ d="M 1.203125 -7 L 2.359375 -7 L 2.359375 0.125 C 2.359375 1.019531 2.1875 1.664062 1.84375 2.0625 C 1.507812 2.457031 0.960938 2.65625 0.203125 2.65625 L -0.234375 2.65625 L -0.234375 1.6875 L 0.078125 1.6875 C 0.515625 1.6875 0.8125 1.582031 0.96875 1.375 C 1.125 1.175781 1.203125 0.757812 1.203125 0.125 Z M 1.203125 -9.71875 L 2.359375 -9.71875 L 2.359375 -8.265625 L 1.203125 -8.265625 Z M 1.203125 -9.71875 "
+ id="path1800" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-23">
+ <path
+ style="stroke:none;"
+ d="M 1.09375 -2.765625 L 1.09375 -7 L 2.234375 -7 L 2.234375 -2.8125 C 2.234375 -2.144531 2.363281 -1.644531 2.625 -1.3125 C 2.882812 -0.976562 3.269531 -0.8125 3.78125 -0.8125 C 4.40625 -0.8125 4.894531 -1.007812 5.25 -1.40625 C 5.613281 -1.800781 5.796875 -2.34375 5.796875 -3.03125 L 5.796875 -7 L 6.953125 -7 L 6.953125 0 L 5.796875 0 L 5.796875 -1.078125 C 5.515625 -0.648438 5.191406 -0.332031 4.828125 -0.125 C 4.460938 0.0820312 4.035156 0.1875 3.546875 0.1875 C 2.742188 0.1875 2.132812 -0.0625 1.71875 -0.5625 C 1.300781 -1.0625 1.09375 -1.796875 1.09375 -2.765625 Z M 3.984375 -7.171875 Z M 3.984375 -7.171875 "
+ id="path1803" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-24">
+ <path
+ style="stroke:none;"
+ d="M 6.515625 2.125 L 6.515625 3.015625 L -0.125 3.015625 L -0.125 2.125 Z M 6.515625 2.125 "
+ id="path1806" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-25">
+ <path
+ style="stroke:none;"
+ d="M 7.1875 -3.78125 L 7.1875 -3.21875 L 1.90625 -3.21875 C 1.957031 -2.425781 2.195312 -1.820312 2.625 -1.40625 C 3.050781 -1 3.644531 -0.796875 4.40625 -0.796875 C 4.84375 -0.796875 5.269531 -0.847656 5.6875 -0.953125 C 6.101562 -1.066406 6.515625 -1.226562 6.921875 -1.4375 L 6.921875 -0.359375 C 6.515625 -0.179688 6.09375 -0.046875 5.65625 0.046875 C 5.21875 0.140625 4.78125 0.1875 4.34375 0.1875 C 3.21875 0.1875 2.328125 -0.132812 1.671875 -0.78125 C 1.023438 -1.4375 0.703125 -2.320312 0.703125 -3.4375 C 0.703125 -4.582031 1.007812 -5.488281 1.625 -6.15625 C 2.25 -6.832031 3.085938 -7.171875 4.140625 -7.171875 C 5.078125 -7.171875 5.816406 -6.863281 6.359375 -6.25 C 6.910156 -5.644531 7.1875 -4.820312 7.1875 -3.78125 Z M 6.046875 -4.125 C 6.035156 -4.75 5.859375 -5.25 5.515625 -5.625 C 5.171875 -6 4.71875 -6.1875 4.15625 -6.1875 C 3.507812 -6.1875 2.992188 -6.003906 2.609375 -5.640625 C 2.222656 -5.285156 2 -4.78125 1.9375 -4.125 Z M 6.046875 -4.125 "
+ id="path1809" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-26">
+ <path
+ style="stroke:none;"
+ d="M 6.25 -6.734375 L 6.25 -5.65625 C 5.914062 -5.832031 5.585938 -5.960938 5.265625 -6.046875 C 4.941406 -6.140625 4.613281 -6.1875 4.28125 -6.1875 C 3.53125 -6.1875 2.945312 -5.953125 2.53125 -5.484375 C 2.125 -5.015625 1.921875 -4.351562 1.921875 -3.5 C 1.921875 -2.644531 2.125 -1.976562 2.53125 -1.5 C 2.945312 -1.03125 3.53125 -0.796875 4.28125 -0.796875 C 4.613281 -0.796875 4.941406 -0.835938 5.265625 -0.921875 C 5.585938 -1.015625 5.914062 -1.148438 6.25 -1.328125 L 6.25 -0.265625 C 5.925781 -0.117188 5.59375 -0.0078125 5.25 0.0625 C 4.90625 0.144531 4.539062 0.1875 4.15625 0.1875 C 3.09375 0.1875 2.25 -0.144531 1.625 -0.8125 C 1.007812 -1.476562 0.703125 -2.375 0.703125 -3.5 C 0.703125 -4.632812 1.015625 -5.53125 1.640625 -6.1875 C 2.273438 -6.84375 3.132812 -7.171875 4.21875 -7.171875 C 4.570312 -7.171875 4.914062 -7.132812 5.25 -7.0625 C 5.59375 -6.988281 5.925781 -6.878906 6.25 -6.734375 Z M 6.25 -6.734375 "
+ id="path1812" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-27">
+ <path
+ style="stroke:none;"
+ d="M 3.921875 -6.1875 C 3.304688 -6.1875 2.816406 -5.945312 2.453125 -5.46875 C 2.097656 -4.988281 1.921875 -4.332031 1.921875 -3.5 C 1.921875 -2.65625 2.097656 -1.992188 2.453125 -1.515625 C 2.804688 -1.035156 3.296875 -0.796875 3.921875 -0.796875 C 4.535156 -0.796875 5.019531 -1.035156 5.375 -1.515625 C 5.726562 -2.003906 5.90625 -2.664062 5.90625 -3.5 C 5.90625 -4.320312 5.726562 -4.972656 5.375 -5.453125 C 5.019531 -5.941406 4.535156 -6.1875 3.921875 -6.1875 Z M 3.921875 -7.171875 C 4.921875 -7.171875 5.703125 -6.84375 6.265625 -6.1875 C 6.835938 -5.539062 7.125 -4.644531 7.125 -3.5 C 7.125 -2.351562 6.835938 -1.453125 6.265625 -0.796875 C 5.703125 -0.140625 4.921875 0.1875 3.921875 0.1875 C 2.910156 0.1875 2.117188 -0.140625 1.546875 -0.796875 C 0.984375 -1.453125 0.703125 -2.351562 0.703125 -3.5 C 0.703125 -4.644531 0.984375 -5.539062 1.546875 -6.1875 C 2.117188 -6.84375 2.910156 -7.171875 3.921875 -7.171875 Z M 3.921875 -7.171875 "
+ id="path1815" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-28">
+ <path
+ style="stroke:none;"
+ d="M 3.96875 -9.703125 C 3.40625 -8.742188 2.988281 -7.796875 2.71875 -6.859375 C 2.445312 -5.929688 2.3125 -4.984375 2.3125 -4.015625 C 2.3125 -3.054688 2.445312 -2.101562 2.71875 -1.15625 C 3 -0.21875 3.414062 0.726562 3.96875 1.6875 L 2.96875 1.6875 C 2.34375 0.707031 1.875 -0.253906 1.5625 -1.203125 C 1.25 -2.148438 1.09375 -3.085938 1.09375 -4.015625 C 1.09375 -4.941406 1.25 -5.875 1.5625 -6.8125 C 1.875 -7.757812 2.34375 -8.722656 2.96875 -9.703125 Z M 3.96875 -9.703125 "
+ id="path1818" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-29">
+ <path
+ style="stroke:none;"
+ d="M 1.03125 -9.703125 L 2.03125 -9.703125 C 2.65625 -8.722656 3.117188 -7.757812 3.421875 -6.8125 C 3.734375 -5.875 3.890625 -4.941406 3.890625 -4.015625 C 3.890625 -3.085938 3.734375 -2.148438 3.421875 -1.203125 C 3.117188 -0.253906 2.65625 0.707031 2.03125 1.6875 L 1.03125 1.6875 C 1.582031 0.726562 1.992188 -0.21875 2.265625 -1.15625 C 2.535156 -2.101562 2.671875 -3.054688 2.671875 -4.015625 C 2.671875 -4.984375 2.535156 -5.929688 2.265625 -6.859375 C 1.992188 -7.796875 1.582031 -8.742188 1.03125 -9.703125 Z M 1.03125 -9.703125 "
+ id="path1821" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-30">
+ <path
+ style="stroke:none;"
+ d="M 4.0625 -4.4375 C 3.46875 -4.4375 3 -4.273438 2.65625 -3.953125 C 2.3125 -3.628906 2.140625 -3.1875 2.140625 -2.625 C 2.140625 -2.0625 2.3125 -1.617188 2.65625 -1.296875 C 3 -0.972656 3.46875 -0.8125 4.0625 -0.8125 C 4.664062 -0.8125 5.140625 -0.972656 5.484375 -1.296875 C 5.828125 -1.617188 6 -2.0625 6 -2.625 C 6 -3.1875 5.828125 -3.628906 5.484375 -3.953125 C 5.140625 -4.273438 4.664062 -4.4375 4.0625 -4.4375 Z M 2.8125 -4.96875 C 2.269531 -5.101562 1.847656 -5.351562 1.546875 -5.71875 C 1.242188 -6.09375 1.09375 -6.546875 1.09375 -7.078125 C 1.09375 -7.828125 1.359375 -8.414062 1.890625 -8.84375 C 2.421875 -9.28125 3.144531 -9.5 4.0625 -9.5 C 5 -9.5 5.726562 -9.28125 6.25 -8.84375 C 6.78125 -8.414062 7.046875 -7.828125 7.046875 -7.078125 C 7.046875 -6.546875 6.894531 -6.09375 6.59375 -5.71875 C 6.289062 -5.351562 5.875 -5.101562 5.34375 -4.96875 C 5.945312 -4.820312 6.414062 -4.539062 6.75 -4.125 C 7.09375 -3.71875 7.265625 -3.21875 7.265625 -2.625 C 7.265625 -1.71875 6.988281 -1.019531 6.4375 -0.53125 C 5.882812 -0.0507812 5.09375 0.1875 4.0625 0.1875 C 3.039062 0.1875 2.253906 -0.0507812 1.703125 -0.53125 C 1.148438 -1.019531 0.875 -1.71875 0.875 -2.625 C 0.875 -3.21875 1.039062 -3.71875 1.375 -4.125 C 1.71875 -4.539062 2.195312 -4.820312 2.8125 -4.96875 Z M 2.34375 -6.953125 C 2.34375 -6.472656 2.492188 -6.097656 2.796875 -5.828125 C 3.097656 -5.554688 3.519531 -5.421875 4.0625 -5.421875 C 4.601562 -5.421875 5.023438 -5.554688 5.328125 -5.828125 C 5.640625 -6.097656 5.796875 -6.472656 5.796875 -6.953125 C 5.796875 -7.441406 5.640625 -7.820312 5.328125 -8.09375 C 5.023438 -8.363281 4.601562 -8.5 4.0625 -8.5 C 3.519531 -8.5 3.097656 -8.363281 2.796875 -8.09375 C 2.492188 -7.820312 2.34375 -7.441406 2.34375 -6.953125 Z M 2.34375 -6.953125 "
+ id="path1824" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-31">
+ <path
+ style="stroke:none;"
+ d="M 1.9375 -1.59375 L 3.203125 -1.59375 L 3.203125 0 L 1.9375 0 Z M 1.9375 -9.328125 L 3.203125 -9.328125 L 3.203125 -5.234375 L 3.078125 -3 L 2.0625 -3 L 1.9375 -5.234375 Z M 1.9375 -9.328125 "
+ id="path1827" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-32">
+ <path
+ style="stroke:none;"
+ d="M 1.359375 -5.8125 L 9.359375 -5.8125 L 9.359375 -4.765625 L 1.359375 -4.765625 Z M 1.359375 -3.265625 L 9.359375 -3.265625 L 9.359375 -2.203125 L 1.359375 -2.203125 Z M 1.359375 -3.265625 "
+ id="path1830" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-33">
+ <path
+ style="stroke:none;"
+ d="M 4.75 -9.71875 L 4.75 -8.765625 L 3.65625 -8.765625 C 3.238281 -8.765625 2.945312 -8.679688 2.78125 -8.515625 C 2.625 -8.347656 2.546875 -8.046875 2.546875 -7.609375 L 2.546875 -7 L 4.4375 -7 L 4.4375 -6.109375 L 2.546875 -6.109375 L 2.546875 0 L 1.390625 0 L 1.390625 -6.109375 L 0.296875 -6.109375 L 0.296875 -7 L 1.390625 -7 L 1.390625 -7.484375 C 1.390625 -8.265625 1.570312 -8.832031 1.9375 -9.1875 C 2.300781 -9.539062 2.875 -9.71875 3.65625 -9.71875 Z M 4.75 -9.71875 "
+ id="path1833" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-34">
+ <path
+ style="stroke:none;"
+ d="M 2.296875 -9.328125 L 2.296875 -5.859375 L 1.234375 -5.859375 L 1.234375 -9.328125 Z M 4.65625 -9.328125 L 4.65625 -5.859375 L 3.59375 -5.859375 L 3.59375 -9.328125 Z M 4.65625 -9.328125 "
+ id="path1836" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-0">
+ <path
+ style="stroke:none;"
+ d="M 0.984375 3.484375 L 0.984375 -13.921875 L 10.859375 -13.921875 L 10.859375 3.484375 Z M 2.09375 2.390625 L 9.765625 2.390625 L 9.765625 -12.8125 L 2.09375 -12.8125 Z M 2.09375 2.390625 "
+ id="path1839" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-1">
+ <path
+ style="stroke:none;"
+ d="M 12.515625 -6.578125 L 12.515625 0 L 9.046875 0 L 9.046875 -5.03125 C 9.046875 -5.96875 9.023438 -6.613281 8.984375 -6.96875 C 8.941406 -7.320312 8.867188 -7.582031 8.765625 -7.75 C 8.628906 -7.96875 8.445312 -8.140625 8.21875 -8.265625 C 7.988281 -8.390625 7.722656 -8.453125 7.421875 -8.453125 C 6.703125 -8.453125 6.132812 -8.175781 5.71875 -7.625 C 5.3125 -7.070312 5.109375 -6.300781 5.109375 -5.3125 L 5.109375 0 L 1.65625 0 L 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 -9.21875 C 5.628906 -9.851562 6.179688 -10.316406 6.765625 -10.609375 C 7.347656 -10.910156 7.992188 -11.0625 8.703125 -11.0625 C 9.953125 -11.0625 10.898438 -10.675781 11.546875 -9.90625 C 12.191406 -9.144531 12.515625 -8.035156 12.515625 -6.578125 Z M 12.515625 -6.578125 "
+ id="path1842" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-2">
+ <path
+ style="stroke:none;"
+ d="M 5.109375 -1.5625 L 5.109375 4.109375 L 1.65625 4.109375 L 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 -9.21875 C 5.585938 -9.851562 6.113281 -10.316406 6.6875 -10.609375 C 7.269531 -10.910156 7.9375 -11.0625 8.6875 -11.0625 C 10.019531 -11.0625 11.113281 -10.53125 11.96875 -9.46875 C 12.820312 -8.414062 13.25 -7.054688 13.25 -5.390625 C 13.25 -3.722656 12.820312 -2.359375 11.96875 -1.296875 C 11.113281 -0.242188 10.019531 0.28125 8.6875 0.28125 C 7.9375 0.28125 7.269531 0.128906 6.6875 -0.171875 C 6.113281 -0.472656 5.585938 -0.9375 5.109375 -1.5625 Z M 7.40625 -8.546875 C 6.664062 -8.546875 6.097656 -8.273438 5.703125 -7.734375 C 5.304688 -7.191406 5.109375 -6.410156 5.109375 -5.390625 C 5.109375 -4.367188 5.304688 -3.585938 5.703125 -3.046875 C 6.097656 -2.503906 6.664062 -2.234375 7.40625 -2.234375 C 8.144531 -2.234375 8.707031 -2.5 9.09375 -3.03125 C 9.488281 -3.570312 9.6875 -4.359375 9.6875 -5.390625 C 9.6875 -6.421875 9.488281 -7.203125 9.09375 -7.734375 C 8.707031 -8.273438 8.144531 -8.546875 7.40625 -8.546875 Z M 7.40625 -8.546875 "
+ id="path1845" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-3">
+ <path
+ style="stroke:none;"
+ d="M 2.015625 -3.734375 L 5.484375 -3.734375 L 5.484375 0 L 2.015625 0 Z M 2.015625 -3.734375 "
+ id="path1848" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-4">
+ <path
+ style="stroke:none;"
+ d="M 6.5 -4.859375 C 5.78125 -4.859375 5.238281 -4.734375 4.875 -4.484375 C 4.507812 -4.242188 4.328125 -3.882812 4.328125 -3.40625 C 4.328125 -2.976562 4.472656 -2.640625 4.765625 -2.390625 C 5.054688 -2.140625 5.460938 -2.015625 5.984375 -2.015625 C 6.640625 -2.015625 7.1875 -2.242188 7.625 -2.703125 C 8.070312 -3.171875 8.296875 -3.757812 8.296875 -4.46875 L 8.296875 -4.859375 Z M 11.78125 -6.15625 L 11.78125 0 L 8.296875 0 L 8.296875 -1.59375 C 7.828125 -0.945312 7.300781 -0.472656 6.71875 -0.171875 C 6.144531 0.128906 5.445312 0.28125 4.625 0.28125 C 3.5 0.28125 2.585938 -0.0390625 1.890625 -0.6875 C 1.191406 -1.34375 0.84375 -2.191406 0.84375 -3.234375 C 0.84375 -4.503906 1.28125 -5.4375 2.15625 -6.03125 C 3.03125 -6.625 4.398438 -6.921875 6.265625 -6.921875 L 8.296875 -6.921875 L 8.296875 -7.1875 C 8.296875 -7.726562 8.078125 -8.125 7.640625 -8.375 C 7.210938 -8.632812 6.539062 -8.765625 5.625 -8.765625 C 4.882812 -8.765625 4.195312 -8.691406 3.5625 -8.546875 C 2.925781 -8.398438 2.335938 -8.175781 1.796875 -7.875 L 1.796875 -10.515625 C 2.535156 -10.691406 3.273438 -10.828125 4.015625 -10.921875 C 4.765625 -11.015625 5.515625 -11.0625 6.265625 -11.0625 C 8.210938 -11.0625 9.617188 -10.675781 10.484375 -9.90625 C 11.347656 -9.132812 11.78125 -7.882812 11.78125 -6.15625 Z M 11.78125 -6.15625 "
+ id="path1851" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-5">
+ <path
+ style="stroke:none;"
+ d="M 9.6875 -7.859375 C 9.382812 -8.003906 9.082031 -8.109375 8.78125 -8.171875 C 8.476562 -8.242188 8.175781 -8.28125 7.875 -8.28125 C 6.988281 -8.28125 6.304688 -7.992188 5.828125 -7.421875 C 5.347656 -6.847656 5.109375 -6.03125 5.109375 -4.96875 L 5.109375 0 L 1.65625 0 L 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 -9.03125 C 5.554688 -9.738281 6.066406 -10.253906 6.640625 -10.578125 C 7.210938 -10.898438 7.898438 -11.0625 8.703125 -11.0625 C 8.816406 -11.0625 8.941406 -11.054688 9.078125 -11.046875 C 9.210938 -11.035156 9.410156 -11.015625 9.671875 -10.984375 Z M 9.6875 -7.859375 "
+ id="path1854" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-6">
+ <path
+ style="stroke:none;"
+ d="M 0.234375 -10.796875 L 3.6875 -10.796875 L 6.59375 -3.46875 L 9.0625 -10.796875 L 12.515625 -10.796875 L 7.96875 1.015625 C 7.519531 2.222656 6.988281 3.066406 6.375 3.546875 C 5.769531 4.023438 4.96875 4.265625 3.96875 4.265625 L 1.984375 4.265625 L 1.984375 2 L 3.0625 2 C 3.644531 2 4.066406 1.90625 4.328125 1.71875 C 4.597656 1.53125 4.804688 1.195312 4.953125 0.71875 L 5.046875 0.421875 Z M 0.234375 -10.796875 "
+ id="path1857" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-7">
+ <path
+ style="stroke:none;"
+ d="M 7.4375 2.609375 L 4.578125 2.609375 C 3.597656 1.015625 2.875 -0.492188 2.40625 -1.921875 C 1.9375 -3.347656 1.703125 -4.769531 1.703125 -6.1875 C 1.703125 -7.59375 1.9375 -9.015625 2.40625 -10.453125 C 2.875 -11.898438 3.597656 -13.410156 4.578125 -14.984375 L 7.4375 -14.984375 C 6.613281 -13.460938 5.992188 -11.972656 5.578125 -10.515625 C 5.171875 -9.054688 4.96875 -7.617188 4.96875 -6.203125 C 4.96875 -4.773438 5.171875 -3.332031 5.578125 -1.875 C 5.992188 -0.414062 6.613281 1.078125 7.4375 2.609375 Z M 7.4375 2.609375 "
+ id="path1860" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-8">
+ <path
+ style="stroke:none;"
+ d="M 7.265625 -11.34375 L 3.203125 -5.3125 L 7.265625 -5.3125 Z M 6.65625 -14.390625 L 10.78125 -14.390625 L 10.78125 -5.3125 L 12.828125 -5.3125 L 12.828125 -2.625 L 10.78125 -2.625 L 10.78125 0 L 7.265625 0 L 7.265625 -2.625 L 0.890625 -2.625 L 0.890625 -5.8125 Z M 6.65625 -14.390625 "
+ id="path1863" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-9">
+ <path
+ style="stroke:none;"
+ d="M 5.6875 -2.734375 L 12.03125 -2.734375 L 12.03125 0 L 1.5625 0 L 1.5625 -2.734375 L 6.8125 -7.375 C 7.28125 -7.789062 7.628906 -8.203125 7.859375 -8.609375 C 8.085938 -9.015625 8.203125 -9.4375 8.203125 -9.875 C 8.203125 -10.550781 7.972656 -11.09375 7.515625 -11.5 C 7.066406 -11.914062 6.460938 -12.125 5.703125 -12.125 C 5.128906 -12.125 4.5 -12 3.8125 -11.75 C 3.125 -11.5 2.382812 -11.128906 1.59375 -10.640625 L 1.59375 -13.8125 C 2.4375 -14.082031 3.265625 -14.289062 4.078125 -14.4375 C 4.890625 -14.582031 5.691406 -14.65625 6.484375 -14.65625 C 8.203125 -14.65625 9.535156 -14.273438 10.484375 -13.515625 C 11.441406 -12.753906 11.921875 -11.695312 11.921875 -10.34375 C 11.921875 -9.5625 11.71875 -8.832031 11.3125 -8.15625 C 10.914062 -7.476562 10.066406 -6.566406 8.765625 -5.421875 Z M 5.6875 -2.734375 "
+ id="path1866" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-10">
+ <path
+ style="stroke:none;"
+ d="M 2.015625 -3.734375 L 5.484375 -3.734375 L 5.484375 -0.796875 L 3.109375 2.8125 L 1.046875 2.8125 L 2.015625 -0.796875 Z M 2.015625 -3.734375 "
+ id="path1869" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-11">
+ <path
+ style="stroke:none;"
+ d=""
+ id="path1872" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-12">
+ <path
+ style="stroke:none;"
+ d="M 9 -9.21875 L 9 -15 L 12.484375 -15 L 12.484375 0 L 9 0 L 9 -1.5625 C 8.53125 -0.925781 8.007812 -0.457031 7.4375 -0.15625 C 6.863281 0.132812 6.203125 0.28125 5.453125 0.28125 C 4.117188 0.28125 3.023438 -0.242188 2.171875 -1.296875 C 1.316406 -2.359375 0.890625 -3.722656 0.890625 -5.390625 C 0.890625 -7.054688 1.316406 -8.414062 2.171875 -9.46875 C 3.023438 -10.53125 4.117188 -11.0625 5.453125 -11.0625 C 6.191406 -11.0625 6.847656 -10.910156 7.421875 -10.609375 C 8.003906 -10.316406 8.53125 -9.851562 9 -9.21875 Z M 6.734375 -2.234375 C 7.472656 -2.234375 8.035156 -2.5 8.421875 -3.03125 C 8.804688 -3.570312 9 -4.359375 9 -5.390625 C 9 -6.421875 8.804688 -7.203125 8.421875 -7.734375 C 8.035156 -8.273438 7.472656 -8.546875 6.734375 -8.546875 C 5.992188 -8.546875 5.429688 -8.273438 5.046875 -7.734375 C 4.660156 -7.203125 4.46875 -6.421875 4.46875 -5.390625 C 4.46875 -4.359375 4.660156 -3.570312 5.046875 -3.03125 C 5.429688 -2.5 5.992188 -2.234375 6.734375 -2.234375 Z M 6.734375 -2.234375 "
+ id="path1875" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-13">
+ <path
+ style="stroke:none;"
+ d="M 5.421875 -13.875 L 5.421875 -10.796875 L 8.984375 -10.796875 L 8.984375 -8.328125 L 5.421875 -8.328125 L 5.421875 -3.75 C 5.421875 -3.25 5.519531 -2.910156 5.71875 -2.734375 C 5.925781 -2.554688 6.328125 -2.46875 6.921875 -2.46875 L 8.6875 -2.46875 L 8.6875 0 L 5.734375 0 C 4.367188 0 3.398438 -0.28125 2.828125 -0.84375 C 2.265625 -1.414062 1.984375 -2.382812 1.984375 -3.75 L 1.984375 -8.328125 L 0.265625 -8.328125 L 0.265625 -10.796875 L 1.984375 -10.796875 L 1.984375 -13.875 Z M 5.421875 -13.875 "
+ id="path1878" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-14">
+ <path
+ style="stroke:none;"
+ d="M 12.4375 -5.421875 L 12.4375 -4.453125 L 4.375 -4.453125 C 4.457031 -3.640625 4.75 -3.03125 5.25 -2.625 C 5.75 -2.21875 6.445312 -2.015625 7.34375 -2.015625 C 8.070312 -2.015625 8.816406 -2.117188 9.578125 -2.328125 C 10.335938 -2.546875 11.117188 -2.875 11.921875 -3.3125 L 11.921875 -0.65625 C 11.109375 -0.34375 10.289062 -0.109375 9.46875 0.046875 C 8.65625 0.203125 7.84375 0.28125 7.03125 0.28125 C 5.070312 0.28125 3.550781 -0.210938 2.46875 -1.203125 C 1.382812 -2.203125 0.84375 -3.597656 0.84375 -5.390625 C 0.84375 -7.148438 1.375 -8.535156 2.4375 -9.546875 C 3.507812 -10.554688 4.976562 -11.0625 6.84375 -11.0625 C 8.539062 -11.0625 9.894531 -10.550781 10.90625 -9.53125 C 11.925781 -8.507812 12.4375 -7.140625 12.4375 -5.421875 Z M 8.890625 -6.578125 C 8.890625 -7.234375 8.695312 -7.757812 8.3125 -8.15625 C 7.9375 -8.5625 7.4375 -8.765625 6.8125 -8.765625 C 6.144531 -8.765625 5.601562 -8.578125 5.1875 -8.203125 C 4.769531 -7.828125 4.507812 -7.285156 4.40625 -6.578125 Z M 8.890625 -6.578125 "
+ id="path1881" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-15">
+ <path
+ style="stroke:none;"
+ d="M 2.09375 -9.515625 L 14.453125 -9.515625 L 14.453125 -7.25 L 2.09375 -7.25 Z M 2.09375 -5.125 L 14.453125 -5.125 L 14.453125 -2.84375 L 2.09375 -2.84375 Z M 2.09375 -5.125 "
+ id="path1884" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-16">
+ <path
+ style="stroke:none;"
+ d="M 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 0 L 1.65625 0 Z M 1.65625 -15 L 5.109375 -15 L 5.109375 -12.1875 L 1.65625 -12.1875 Z M 1.65625 -15 "
+ id="path1887" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-17">
+ <path
+ style="stroke:none;"
+ d="M 1.578125 2.609375 C 2.398438 1.078125 3.015625 -0.414062 3.421875 -1.875 C 3.835938 -3.332031 4.046875 -4.773438 4.046875 -6.203125 C 4.046875 -7.617188 3.835938 -9.054688 3.421875 -10.515625 C 3.015625 -11.972656 2.398438 -13.460938 1.578125 -14.984375 L 4.453125 -14.984375 C 5.421875 -13.410156 6.140625 -11.898438 6.609375 -10.453125 C 7.085938 -9.015625 7.328125 -7.59375 7.328125 -6.1875 C 7.328125 -4.769531 7.09375 -3.347656 6.625 -1.921875 C 6.15625 -0.492188 5.429688 1.015625 4.453125 2.609375 Z M 1.578125 2.609375 "
+ id="path1890" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-18">
+ <path
+ style="stroke:none;"
+ d="M 10.09375 -10.46875 L 10.09375 -7.84375 C 9.351562 -8.144531 8.640625 -8.375 7.953125 -8.53125 C 7.265625 -8.6875 6.617188 -8.765625 6.015625 -8.765625 C 5.359375 -8.765625 4.867188 -8.679688 4.546875 -8.515625 C 4.222656 -8.359375 4.0625 -8.109375 4.0625 -7.765625 C 4.0625 -7.484375 4.179688 -7.269531 4.421875 -7.125 C 4.671875 -6.976562 5.109375 -6.867188 5.734375 -6.796875 L 6.328125 -6.71875 C 8.097656 -6.488281 9.285156 -6.113281 9.890625 -5.59375 C 10.503906 -5.082031 10.8125 -4.28125 10.8125 -3.1875 C 10.8125 -2.03125 10.390625 -1.160156 9.546875 -0.578125 C 8.703125 -0.00390625 7.4375 0.28125 5.75 0.28125 C 5.03125 0.28125 4.289062 0.222656 3.53125 0.109375 C 2.769531 -0.00390625 1.988281 -0.171875 1.1875 -0.390625 L 1.1875 -3.015625 C 1.875 -2.679688 2.578125 -2.429688 3.296875 -2.265625 C 4.023438 -2.097656 4.757812 -2.015625 5.5 -2.015625 C 6.175781 -2.015625 6.6875 -2.109375 7.03125 -2.296875 C 7.375 -2.484375 7.546875 -2.757812 7.546875 -3.125 C 7.546875 -3.4375 7.425781 -3.664062 7.1875 -3.8125 C 6.957031 -3.96875 6.488281 -4.085938 5.78125 -4.171875 L 5.171875 -4.25 C 3.640625 -4.4375 2.5625 -4.789062 1.9375 -5.3125 C 1.320312 -5.832031 1.015625 -6.625 1.015625 -7.6875 C 1.015625 -8.832031 1.40625 -9.679688 2.1875 -10.234375 C 2.976562 -10.785156 4.1875 -11.0625 5.8125 -11.0625 C 6.445312 -11.0625 7.113281 -11.007812 7.8125 -10.90625 C 8.507812 -10.8125 9.269531 -10.664062 10.09375 -10.46875 Z M 10.09375 -10.46875 "
+ id="path1893" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-19">
+ <path
+ style="stroke:none;"
+ d="M 8.40625 -14.390625 L 8.40625 -9.046875 L 6.125 -9.046875 L 6.125 -14.390625 Z M 4.171875 -14.390625 L 4.171875 -9.046875 L 1.875 -9.046875 L 1.875 -14.390625 Z M 4.171875 -14.390625 "
+ id="path1896" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-20">
+ <path
+ style="stroke:none;"
+ d="M 11.828125 -13.9375 L 11.828125 -10.890625 C 11.035156 -11.242188 10.265625 -11.507812 9.515625 -11.6875 C 8.765625 -11.875 8.054688 -11.96875 7.390625 -11.96875 C 6.503906 -11.96875 5.847656 -11.84375 5.421875 -11.59375 C 4.992188 -11.351562 4.78125 -10.976562 4.78125 -10.46875 C 4.78125 -10.082031 4.921875 -9.78125 5.203125 -9.5625 C 5.492188 -9.34375 6.015625 -9.15625 6.765625 -9 L 8.34375 -8.6875 C 9.945312 -8.363281 11.085938 -7.875 11.765625 -7.21875 C 12.441406 -6.5625 12.78125 -5.628906 12.78125 -4.421875 C 12.78125 -2.835938 12.304688 -1.65625 11.359375 -0.875 C 10.421875 -0.101562 8.984375 0.28125 7.046875 0.28125 C 6.140625 0.28125 5.222656 0.191406 4.296875 0.015625 C 3.378906 -0.148438 2.460938 -0.40625 1.546875 -0.75 L 1.546875 -3.890625 C 2.460938 -3.398438 3.347656 -3.03125 4.203125 -2.78125 C 5.066406 -2.53125 5.894531 -2.40625 6.6875 -2.40625 C 7.5 -2.40625 8.117188 -2.539062 8.546875 -2.8125 C 8.984375 -3.082031 9.203125 -3.46875 9.203125 -3.96875 C 9.203125 -4.414062 9.054688 -4.757812 8.765625 -5 C 8.472656 -5.25 7.890625 -5.472656 7.015625 -5.671875 L 5.578125 -5.984375 C 4.128906 -6.296875 3.070312 -6.789062 2.40625 -7.46875 C 1.75 -8.144531 1.421875 -9.050781 1.421875 -10.1875 C 1.421875 -11.625 1.878906 -12.726562 2.796875 -13.5 C 3.722656 -14.269531 5.054688 -14.65625 6.796875 -14.65625 C 7.585938 -14.65625 8.398438 -14.59375 9.234375 -14.46875 C 10.078125 -14.351562 10.941406 -14.175781 11.828125 -13.9375 Z M 11.828125 -13.9375 "
+ id="path1899" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-21">
+ <path
+ style="stroke:none;"
+ d="M 9.078125 -7.21875 C 9.078125 -9.007812 8.910156 -10.273438 8.578125 -11.015625 C 8.242188 -11.753906 7.675781 -12.125 6.875 -12.125 C 6.082031 -12.125 5.515625 -11.753906 5.171875 -11.015625 C 4.828125 -10.273438 4.65625 -9.007812 4.65625 -7.21875 C 4.65625 -5.394531 4.828125 -4.109375 5.171875 -3.359375 C 5.515625 -2.617188 6.082031 -2.25 6.875 -2.25 C 7.664062 -2.25 8.226562 -2.617188 8.5625 -3.359375 C 8.90625 -4.109375 9.078125 -5.394531 9.078125 -7.21875 Z M 12.796875 -7.1875 C 12.796875 -4.800781 12.28125 -2.957031 11.25 -1.65625 C 10.226562 -0.363281 8.769531 0.28125 6.875 0.28125 C 4.976562 0.28125 3.515625 -0.363281 2.484375 -1.65625 C 1.453125 -2.957031 0.9375 -4.800781 0.9375 -7.1875 C 0.9375 -9.570312 1.453125 -11.410156 2.484375 -12.703125 C 3.515625 -14.003906 4.976562 -14.65625 6.875 -14.65625 C 8.769531 -14.65625 10.226562 -14.003906 11.25 -12.703125 C 12.28125 -11.410156 12.796875 -9.570312 12.796875 -7.1875 Z M 12.796875 -7.1875 "
+ id="path1902" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-22">
+ <path
+ style="stroke:none;"
+ d="M 15.578125 -6.859375 L 15.578125 -5.515625 L 11.796875 -1.71875 L 10.390625 -3.125 L 12.3125 -5.03125 L 1.125 -5.03125 L 1.125 -7.34375 L 12.3125 -7.34375 L 10.390625 -9.265625 L 11.796875 -10.65625 Z M 15.578125 -6.859375 "
+ id="path1905" />
+ </symbol>
+ </g>
+ </defs>
+ <g
+ id="surface392452">
+ <rect
+ x="0"
+ y="0"
+ width="908"
+ height="444"
+ style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"
+ id="rect1912" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:0.592157;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 37.690003 18.712741 L 47.059925 18.712741 L 47.059925 20.612741 L 37.690003 20.612741 Z M 37.690003 18.712741 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1914" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g1968">
+ <use
+ xlink:href="#glyph0-1"
+ x="273.335938"
+ y="24.88878"
+ id="use1916" />
+ <use
+ xlink:href="#glyph0-2"
+ x="282.224826"
+ y="24.88878"
+ id="use1918" />
+ <use
+ xlink:href="#glyph0-3"
+ x="290.002604"
+ y="24.88878"
+ id="use1920" />
+ <use
+ xlink:href="#glyph0-4"
+ x="296.669271"
+ y="24.88878"
+ id="use1922" />
+ <use
+ xlink:href="#glyph0-5"
+ x="301.669271"
+ y="24.88878"
+ id="use1924" />
+ <use
+ xlink:href="#glyph0-6"
+ x="305.280382"
+ y="24.88878"
+ id="use1926" />
+ <use
+ xlink:href="#glyph0-7"
+ x="313.335938"
+ y="24.88878"
+ id="use1928" />
+ <use
+ xlink:href="#glyph0-8"
+ x="321.391493"
+ y="24.88878"
+ id="use1930" />
+ <use
+ xlink:href="#glyph0-9"
+ x="325.280382"
+ y="24.88878"
+ id="use1932" />
+ <use
+ xlink:href="#glyph0-10"
+ x="337.780382"
+ y="24.88878"
+ id="use1934" />
+ <use
+ xlink:href="#glyph0-11"
+ x="345.835938"
+ y="24.88878"
+ id="use1936" />
+ <use
+ xlink:href="#glyph0-12"
+ x="349.447049"
+ y="24.88878"
+ id="use1938" />
+ <use
+ xlink:href="#glyph0-8"
+ x="354.447049"
+ y="24.88878"
+ id="use1940" />
+ <use
+ xlink:href="#glyph0-6"
+ x="358.335938"
+ y="24.88878"
+ id="use1942" />
+ <use
+ xlink:href="#glyph0-4"
+ x="366.391493"
+ y="24.88878"
+ id="use1944" />
+ <use
+ xlink:href="#glyph0-13"
+ x="371.391493"
+ y="24.88878"
+ id="use1946" />
+ <use
+ xlink:href="#glyph0-14"
+ x="379.447049"
+ y="24.88878"
+ id="use1948" />
+ <use
+ xlink:href="#glyph0-15"
+ x="387.502604"
+ y="24.88878"
+ id="use1950" />
+ <use
+ xlink:href="#glyph0-16"
+ x="391.669271"
+ y="24.88878"
+ id="use1952" />
+ <use
+ xlink:href="#glyph0-17"
+ x="395.835938"
+ y="24.88878"
+ id="use1954" />
+ <use
+ xlink:href="#glyph0-4"
+ x="403.891493"
+ y="24.88878"
+ id="use1956" />
+ <use
+ xlink:href="#glyph0-18"
+ x="408.891493"
+ y="24.88878"
+ id="use1958" />
+ <use
+ xlink:href="#glyph0-5"
+ x="414.169271"
+ y="24.88878"
+ id="use1960" />
+ <use
+ xlink:href="#glyph0-6"
+ x="417.780382"
+ y="24.88878"
+ id="use1962" />
+ <use
+ xlink:href="#glyph0-7"
+ x="425.835938"
+ y="24.88878"
+ id="use1964" />
+ <use
+ xlink:href="#glyph0-19"
+ x="433.891493"
+ y="24.88878"
+ id="use1966" />
+ </g>
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;"
+ d="M 42.374964 20.662937 L 42.374964 21.218991 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1970" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 42.124964 21.218991 L 42.374964 21.718991 L 42.624964 21.218991 Z M 42.124964 21.218991 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1972" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 32.07594 22.801609 L 36.211292 22.813327 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1974" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 36.586292 22.814499 L 36.085706 23.063132 L 36.211292 22.813327 L 36.087073 22.563132 Z M 36.586292 22.814499 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1976" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 56.489612 22.817429 L 48.53844 22.825046 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1978" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 48.16344 22.825437 L 48.66305 22.574851 L 48.53844 22.825046 L 48.663636 23.074851 Z M 48.16344 22.825437 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1980" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 41.592932 23.830124 L 40.322034 25.453757 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1982" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 40.090979 25.748874 L 40.202307 25.201218 L 40.322034 25.453757 L 40.596057 25.509421 Z M 40.090979 25.748874 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1984" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 43.056604 23.830124 L 44.151331 25.434812 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1986" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 44.362659 25.744577 L 43.874378 25.472507 L 44.151331 25.434812 L 44.287464 25.190671 Z M 44.362659 25.744577 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1988" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(61.176473%,63.921571%,97.647059%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 29.543714 22.614499 L 32.026331 21.881296 L 32.026331 23.714499 L 29.543714 23.714499 Z M 29.543714 22.614499 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path1990" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2002">
+ <use
+ xlink:href="#glyph0-5"
+ x="107.921875"
+ y="94.923937"
+ id="use1992" />
+ <use
+ xlink:href="#glyph0-6"
+ x="111.532986"
+ y="94.923937"
+ id="use1994" />
+ <use
+ xlink:href="#glyph0-4"
+ x="119.588542"
+ y="94.923937"
+ id="use1996" />
+ <use
+ xlink:href="#glyph0-13"
+ x="124.588542"
+ y="94.923937"
+ id="use1998" />
+ <use
+ xlink:href="#glyph0-14"
+ x="132.644097"
+ y="94.923937"
+ id="use2000" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,70.19608%,14.509805%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 56.539612 22.616257 L 58.539612 21.816257 L 58.539612 23.816257 L 56.539612 23.816257 Z M 56.539612 22.616257 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2004" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2012">
+ <use
+ xlink:href="#glyph0-17"
+ x="647.332031"
+ y="95.959093"
+ id="use2006" />
+ <use
+ xlink:href="#glyph0-13"
+ x="655.387587"
+ y="95.959093"
+ id="use2008" />
+ <use
+ xlink:href="#glyph0-20"
+ x="663.443142"
+ y="95.959093"
+ id="use2010" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 36.747425 21.881101 L 48.002503 21.881101 L 48.002503 23.781101 L 36.747425 23.781101 Z M 36.747425 21.881101 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2014" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2076">
+ <use
+ xlink:href="#glyph0-2"
+ x="260.152344"
+ y="88.252062"
+ id="use2016" />
+ <use
+ xlink:href="#glyph0-21"
+ x="267.930122"
+ y="88.252062"
+ id="use2018" />
+ <use
+ xlink:href="#glyph0-22"
+ x="275.985677"
+ y="88.252062"
+ id="use2020" />
+ <use
+ xlink:href="#glyph0-23"
+ x="279.596788"
+ y="88.252062"
+ id="use2022" />
+ <use
+ xlink:href="#glyph0-3"
+ x="287.652344"
+ y="88.252062"
+ id="use2024" />
+ <use
+ xlink:href="#glyph0-4"
+ x="294.31901"
+ y="88.252062"
+ id="use2026" />
+ <use
+ xlink:href="#glyph0-24"
+ x="299.31901"
+ y="88.252062"
+ id="use2028" />
+ <use
+ xlink:href="#glyph0-21"
+ x="305.707899"
+ y="88.252062"
+ id="use2030" />
+ <use
+ xlink:href="#glyph0-25"
+ x="313.763455"
+ y="88.252062"
+ id="use2032" />
+ <use
+ xlink:href="#glyph0-3"
+ x="321.541233"
+ y="88.252062"
+ id="use2034" />
+ <use
+ xlink:href="#glyph0-26"
+ x="328.207899"
+ y="88.252062"
+ id="use2036" />
+ <use
+ xlink:href="#glyph0-18"
+ x="335.152344"
+ y="88.252062"
+ id="use2038" />
+ <use
+ xlink:href="#glyph0-5"
+ x="340.430122"
+ y="88.252062"
+ id="use2040" />
+ <use
+ xlink:href="#glyph0-10"
+ x="344.041233"
+ y="88.252062"
+ id="use2042" />
+ <use
+ xlink:href="#glyph0-4"
+ x="352.096788"
+ y="88.252062"
+ id="use2044" />
+ <use
+ xlink:href="#glyph0-27"
+ x="357.096788"
+ y="88.252062"
+ id="use2046" />
+ <use
+ xlink:href="#glyph0-18"
+ x="364.874566"
+ y="88.252062"
+ id="use2048" />
+ <use
+ xlink:href="#glyph0-3"
+ x="370.152344"
+ y="88.252062"
+ id="use2050" />
+ <use
+ xlink:href="#glyph0-28"
+ x="376.81901"
+ y="88.252062"
+ id="use2052" />
+ <use
+ xlink:href="#glyph0-5"
+ x="381.81901"
+ y="88.252062"
+ id="use2054" />
+ <use
+ xlink:href="#glyph0-6"
+ x="385.430122"
+ y="88.252062"
+ id="use2056" />
+ <use
+ xlink:href="#glyph0-4"
+ x="393.485677"
+ y="88.252062"
+ id="use2058" />
+ <use
+ xlink:href="#glyph0-13"
+ x="398.485677"
+ y="88.252062"
+ id="use2060" />
+ <use
+ xlink:href="#glyph0-14"
+ x="406.541233"
+ y="88.252062"
+ id="use2062" />
+ <use
+ xlink:href="#glyph0-15"
+ x="414.596788"
+ y="88.252062"
+ id="use2064" />
+ <use
+ xlink:href="#glyph0-16"
+ x="418.763455"
+ y="88.252062"
+ id="use2066" />
+ <use
+ xlink:href="#glyph0-17"
+ x="422.930122"
+ y="88.252062"
+ id="use2068" />
+ <use
+ xlink:href="#glyph0-13"
+ x="430.985677"
+ y="88.252062"
+ id="use2070" />
+ <use
+ xlink:href="#glyph0-20"
+ x="439.041233"
+ y="88.252062"
+ id="use2072" />
+ <use
+ xlink:href="#glyph0-29"
+ x="447.096788"
+ y="88.252062"
+ id="use2074" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 37.777112 25.887156 L 41.350745 25.887156 L 40.622815 27.887156 L 37.049182 27.887156 Z M 37.777112 25.887156 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2078" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2090">
+ <use
+ xlink:href="#glyph0-5"
+ x="276.222656"
+ y="169.377062"
+ id="use2080" />
+ <use
+ xlink:href="#glyph0-6"
+ x="279.833767"
+ y="169.377062"
+ id="use2082" />
+ <use
+ xlink:href="#glyph0-4"
+ x="287.889323"
+ y="169.377062"
+ id="use2084" />
+ <use
+ xlink:href="#glyph0-13"
+ x="292.889323"
+ y="169.377062"
+ id="use2086" />
+ <use
+ xlink:href="#glyph0-14"
+ x="300.944878"
+ y="169.377062"
+ id="use2088" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 44.26344 25.887156 L 46.748792 25.887156 L 46.020862 27.887156 L 43.535511 27.887156 Z M 44.26344 25.887156 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2092" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2098">
+ <use
+ xlink:href="#glyph0-17"
+ x="403.40625"
+ y="169.377062"
+ id="use2094" />
+ <use
+ xlink:href="#glyph0-30"
+ x="411.461806"
+ y="169.377062"
+ id="use2096" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 57.539612 25.68364 L 59.946643 26.887156 L 57.539612 28.090671 L 55.132776 26.887156 Z M 57.539612 25.68364 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2100" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2106">
+ <use
+ xlink:href="#glyph0-31"
+ x="651.492188"
+ y="169.377062"
+ id="use2102" />
+ <use
+ xlink:href="#glyph0-32"
+ x="656.492188"
+ y="169.377062"
+ id="use2104" />
+ </g>
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 46.416761 26.887156 L 54.596057 26.887156 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2108" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 54.971057 26.887156 L 54.471057 27.137156 L 54.596057 26.887156 L 54.471057 26.637156 Z M 54.971057 26.887156 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2110" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 57.539612 23.866257 L 57.539612 25.146921 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2112" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 57.539612 25.521921 L 57.289612 25.021921 L 57.539612 25.146921 L 57.789612 25.021921 Z M 57.539612 25.521921 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2114" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:0.592157;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 60.273401 28.318015 L 69.890979 28.318015 L 69.890979 30.218015 L 60.273401 30.218015 Z M 60.273401 28.318015 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2116" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2172">
+ <use
+ xlink:href="#glyph0-1"
+ x="724.980469"
+ y="216.994249"
+ id="use2118" />
+ <use
+ xlink:href="#glyph0-2"
+ x="733.869358"
+ y="216.994249"
+ id="use2120" />
+ <use
+ xlink:href="#glyph0-3"
+ x="741.647135"
+ y="216.994249"
+ id="use2122" />
+ <use
+ xlink:href="#glyph0-4"
+ x="748.313802"
+ y="216.994249"
+ id="use2124" />
+ <use
+ xlink:href="#glyph0-5"
+ x="753.313802"
+ y="216.994249"
+ id="use2126" />
+ <use
+ xlink:href="#glyph0-6"
+ x="756.924913"
+ y="216.994249"
+ id="use2128" />
+ <use
+ xlink:href="#glyph0-7"
+ x="764.980469"
+ y="216.994249"
+ id="use2130" />
+ <use
+ xlink:href="#glyph0-8"
+ x="773.036024"
+ y="216.994249"
+ id="use2132" />
+ <use
+ xlink:href="#glyph0-9"
+ x="776.924913"
+ y="216.994249"
+ id="use2134" />
+ <use
+ xlink:href="#glyph0-10"
+ x="789.424913"
+ y="216.994249"
+ id="use2136" />
+ <use
+ xlink:href="#glyph0-11"
+ x="797.480469"
+ y="216.994249"
+ id="use2138" />
+ <use
+ xlink:href="#glyph0-12"
+ x="801.09158"
+ y="216.994249"
+ id="use2140" />
+ <use
+ xlink:href="#glyph0-17"
+ x="806.09158"
+ y="216.994249"
+ id="use2142" />
+ <use
+ xlink:href="#glyph0-4"
+ x="814.147135"
+ y="216.994249"
+ id="use2144" />
+ <use
+ xlink:href="#glyph0-18"
+ x="819.147135"
+ y="216.994249"
+ id="use2146" />
+ <use
+ xlink:href="#glyph0-5"
+ x="824.424913"
+ y="216.994249"
+ id="use2148" />
+ <use
+ xlink:href="#glyph0-6"
+ x="828.036024"
+ y="216.994249"
+ id="use2150" />
+ <use
+ xlink:href="#glyph0-7"
+ x="836.09158"
+ y="216.994249"
+ id="use2152" />
+ <use
+ xlink:href="#glyph0-15"
+ x="844.147135"
+ y="216.994249"
+ id="use2154" />
+ <use
+ xlink:href="#glyph0-16"
+ x="848.313802"
+ y="216.994249"
+ id="use2156" />
+ <use
+ xlink:href="#glyph0-17"
+ x="852.480469"
+ y="216.994249"
+ id="use2158" />
+ <use
+ xlink:href="#glyph0-4"
+ x="860.536024"
+ y="216.994249"
+ id="use2160" />
+ <use
+ xlink:href="#glyph0-18"
+ x="865.536024"
+ y="216.994249"
+ id="use2162" />
+ <use
+ xlink:href="#glyph0-5"
+ x="870.813802"
+ y="216.994249"
+ id="use2164" />
+ <use
+ xlink:href="#glyph0-6"
+ x="874.424913"
+ y="216.994249"
+ id="use2166" />
+ <use
+ xlink:href="#glyph0-7"
+ x="882.480469"
+ y="216.994249"
+ id="use2168" />
+ <use
+ xlink:href="#glyph0-19"
+ x="890.536024"
+ y="216.994249"
+ id="use2170" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 51.584729 31.317234 L 63.49469 31.317234 L 63.49469 33.217234 L 51.584729 33.217234 Z M 51.584729 31.317234 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2174" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2234">
+ <use
+ xlink:href="#glyph0-7"
+ x="565.378906"
+ y="276.978624"
+ id="use2176" />
+ <use
+ xlink:href="#glyph0-25"
+ x="573.434462"
+ y="276.978624"
+ id="use2178" />
+ <use
+ xlink:href="#glyph0-4"
+ x="581.21224"
+ y="276.978624"
+ id="use2180" />
+ <use
+ xlink:href="#glyph0-24"
+ x="586.21224"
+ y="276.978624"
+ id="use2182" />
+ <use
+ xlink:href="#glyph0-4"
+ x="592.601128"
+ y="276.978624"
+ id="use2184" />
+ <use
+ xlink:href="#glyph0-18"
+ x="597.601128"
+ y="276.978624"
+ id="use2186" />
+ <use
+ xlink:href="#glyph0-2"
+ x="602.878906"
+ y="276.978624"
+ id="use2188" />
+ <use
+ xlink:href="#glyph0-6"
+ x="610.656684"
+ y="276.978624"
+ id="use2190" />
+ <use
+ xlink:href="#glyph0-3"
+ x="618.71224"
+ y="276.978624"
+ id="use2192" />
+ <use
+ xlink:href="#glyph0-33"
+ x="625.378906"
+ y="276.978624"
+ id="use2194" />
+ <use
+ xlink:href="#glyph0-25"
+ x="629.823351"
+ y="276.978624"
+ id="use2196" />
+ <use
+ xlink:href="#glyph0-18"
+ x="637.601128"
+ y="276.978624"
+ id="use2198" />
+ <use
+ xlink:href="#glyph0-33"
+ x="642.878906"
+ y="276.978624"
+ id="use2200" />
+ <use
+ xlink:href="#glyph0-23"
+ x="647.323351"
+ y="276.978624"
+ id="use2202" />
+ <use
+ xlink:href="#glyph0-6"
+ x="655.378906"
+ y="276.978624"
+ id="use2204" />
+ <use
+ xlink:href="#glyph0-26"
+ x="663.434462"
+ y="276.978624"
+ id="use2206" />
+ <use
+ xlink:href="#glyph0-4"
+ x="670.378906"
+ y="276.978624"
+ id="use2208" />
+ <use
+ xlink:href="#glyph0-5"
+ x="675.378906"
+ y="276.978624"
+ id="use2210" />
+ <use
+ xlink:href="#glyph0-27"
+ x="678.990017"
+ y="276.978624"
+ id="use2212" />
+ <use
+ xlink:href="#glyph0-6"
+ x="686.767795"
+ y="276.978624"
+ id="use2214" />
+ <use
+ xlink:href="#glyph0-28"
+ x="694.823351"
+ y="276.978624"
+ id="use2216" />
+ <use
+ xlink:href="#glyph0-17"
+ x="699.823351"
+ y="276.978624"
+ id="use2218" />
+ <use
+ xlink:href="#glyph0-30"
+ x="707.878906"
+ y="276.978624"
+ id="use2220" />
+ <use
+ xlink:href="#glyph0-15"
+ x="715.934462"
+ y="276.978624"
+ id="use2222" />
+ <use
+ xlink:href="#glyph0-16"
+ x="720.101128"
+ y="276.978624"
+ id="use2224" />
+ <use
+ xlink:href="#glyph0-17"
+ x="724.267795"
+ y="276.978624"
+ id="use2226" />
+ <use
+ xlink:href="#glyph0-13"
+ x="732.323351"
+ y="276.978624"
+ id="use2228" />
+ <use
+ xlink:href="#glyph0-20"
+ x="740.378906"
+ y="276.978624"
+ id="use2230" />
+ <use
+ xlink:href="#glyph0-29"
+ x="748.434462"
+ y="276.978624"
+ id="use2232" />
+ </g>
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;"
+ d="M 62.568518 30.267624 L 60.621643 31.041648 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2236" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 60.529456 30.809421 L 60.15719 31.226413 L 60.714026 31.27407 Z M 60.529456 30.809421 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2238" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 57.539612 28.140671 L 57.539612 30.780906 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2240" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 57.539612 31.155906 L 57.289612 30.655906 L 57.539612 30.780906 L 57.789612 30.655906 Z M 57.539612 31.155906 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2242" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 36.420081 31.317234 L 48.330042 31.317234 L 48.330042 33.217234 L 36.420081 33.217234 Z M 36.420081 31.317234 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2244" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2308">
+ <use
+ xlink:href="#glyph0-7"
+ x="257.789062"
+ y="276.978624"
+ id="use2246" />
+ <use
+ xlink:href="#glyph0-25"
+ x="265.844618"
+ y="276.978624"
+ id="use2248" />
+ <use
+ xlink:href="#glyph0-4"
+ x="273.622396"
+ y="276.978624"
+ id="use2250" />
+ <use
+ xlink:href="#glyph0-24"
+ x="278.622396"
+ y="276.978624"
+ id="use2252" />
+ <use
+ xlink:href="#glyph0-4"
+ x="285.011285"
+ y="276.978624"
+ id="use2254" />
+ <use
+ xlink:href="#glyph0-18"
+ x="290.011285"
+ y="276.978624"
+ id="use2256" />
+ <use
+ xlink:href="#glyph0-2"
+ x="295.289062"
+ y="276.978624"
+ id="use2258" />
+ <use
+ xlink:href="#glyph0-6"
+ x="303.06684"
+ y="276.978624"
+ id="use2260" />
+ <use
+ xlink:href="#glyph0-3"
+ x="311.122396"
+ y="276.978624"
+ id="use2262" />
+ <use
+ xlink:href="#glyph0-33"
+ x="317.789062"
+ y="276.978624"
+ id="use2264" />
+ <use
+ xlink:href="#glyph0-25"
+ x="322.233507"
+ y="276.978624"
+ id="use2266" />
+ <use
+ xlink:href="#glyph0-18"
+ x="330.011285"
+ y="276.978624"
+ id="use2268" />
+ <use
+ xlink:href="#glyph0-33"
+ x="335.289062"
+ y="276.978624"
+ id="use2270" />
+ <use
+ xlink:href="#glyph0-23"
+ x="339.733507"
+ y="276.978624"
+ id="use2272" />
+ <use
+ xlink:href="#glyph0-6"
+ x="347.789062"
+ y="276.978624"
+ id="use2274" />
+ <use
+ xlink:href="#glyph0-26"
+ x="355.844618"
+ y="276.978624"
+ id="use2276" />
+ <use
+ xlink:href="#glyph0-4"
+ x="362.789062"
+ y="276.978624"
+ id="use2278" />
+ <use
+ xlink:href="#glyph0-5"
+ x="367.789062"
+ y="276.978624"
+ id="use2280" />
+ <use
+ xlink:href="#glyph0-27"
+ x="371.400174"
+ y="276.978624"
+ id="use2282" />
+ <use
+ xlink:href="#glyph0-6"
+ x="379.177951"
+ y="276.978624"
+ id="use2284" />
+ <use
+ xlink:href="#glyph0-28"
+ x="387.233507"
+ y="276.978624"
+ id="use2286" />
+ <use
+ xlink:href="#glyph0-5"
+ x="392.233507"
+ y="276.978624"
+ id="use2288" />
+ <use
+ xlink:href="#glyph0-6"
+ x="395.844618"
+ y="276.978624"
+ id="use2290" />
+ <use
+ xlink:href="#glyph0-4"
+ x="403.900174"
+ y="276.978624"
+ id="use2292" />
+ <use
+ xlink:href="#glyph0-13"
+ x="408.900174"
+ y="276.978624"
+ id="use2294" />
+ <use
+ xlink:href="#glyph0-14"
+ x="416.955729"
+ y="276.978624"
+ id="use2296" />
+ <use
+ xlink:href="#glyph0-15"
+ x="425.011285"
+ y="276.978624"
+ id="use2298" />
+ <use
+ xlink:href="#glyph0-16"
+ x="429.177951"
+ y="276.978624"
+ id="use2300" />
+ <use
+ xlink:href="#glyph0-17"
+ x="433.344618"
+ y="276.978624"
+ id="use2302" />
+ <use
+ xlink:href="#glyph0-30"
+ x="441.400174"
+ y="276.978624"
+ id="use2304" />
+ <use
+ xlink:href="#glyph0-29"
+ x="449.455729"
+ y="276.978624"
+ id="use2306" />
+ </g>
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 39.807776 27.917038 L 41.537659 30.848484 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2310" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 41.728284 31.171335 L 41.258948 30.86782 L 41.537659 30.848484 L 41.689417 30.613718 Z M 41.728284 31.171335 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2312" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 44.612464 27.917038 L 43.111682 30.834812 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2314" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 42.940198 31.16821 L 42.946643 30.609226 L 43.111682 30.834812 L 43.391175 30.837937 Z M 42.940198 31.16821 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2316" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;"
+ d="M 42.374964 23.831491 L 42.374964 30.654929 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2318" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 42.124964 30.654929 L 42.374964 31.154929 L 42.624964 30.654929 Z M 42.124964 30.654929 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2320" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 30.784925 25.633054 L 33.293128 26.887156 L 30.784925 28.141257 L 28.276917 26.887156 Z M 30.784925 25.633054 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2322" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2330">
+ <use
+ xlink:href="#glyph0-31"
+ x="114.308594"
+ y="169.377062"
+ id="use2324" />
+ <use
+ xlink:href="#glyph0-32"
+ x="119.308594"
+ y="169.377062"
+ id="use2326" />
+ <use
+ xlink:href="#glyph0-16"
+ x="130.141927"
+ y="169.377062"
+ id="use2328" />
+ </g>
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 30.784925 23.76489 L 30.784925 25.096335 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2332" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 30.784925 25.471335 L 30.534925 24.971335 L 30.784925 25.096335 L 31.034925 24.971335 Z M 30.784925 25.471335 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2334" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 37.381214 26.887156 L 33.830042 26.887156 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2336" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 33.455042 26.887156 L 33.955042 26.637156 L 33.830042 26.887156 L 33.955042 27.137156 Z M 33.455042 26.887156 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2338" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(61.176473%,63.921571%,97.647059%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 28.660706 35.381882 L 32.909339 34.542038 L 32.909339 36.642038 L 28.660706 36.642038 Z M 28.660706 35.381882 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2340" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2360">
+ <use
+ xlink:href="#glyph0-5"
+ x="94.875"
+ y="351.869249"
+ id="use2342" />
+ <use
+ xlink:href="#glyph0-6"
+ x="98.486111"
+ y="351.869249"
+ id="use2344" />
+ <use
+ xlink:href="#glyph0-4"
+ x="106.541667"
+ y="351.869249"
+ id="use2346" />
+ <use
+ xlink:href="#glyph0-13"
+ x="111.541667"
+ y="351.869249"
+ id="use2348" />
+ <use
+ xlink:href="#glyph0-14"
+ x="119.597222"
+ y="351.869249"
+ id="use2350" />
+ <use
+ xlink:href="#glyph0-28"
+ x="127.652778"
+ y="351.869249"
+ id="use2352" />
+ <use
+ xlink:href="#glyph0-14"
+ x="132.652778"
+ y="351.869249"
+ id="use2354" />
+ <use
+ xlink:href="#glyph0-13"
+ x="140.708333"
+ y="351.869249"
+ id="use2356" />
+ <use
+ xlink:href="#glyph0-29"
+ x="148.763889"
+ y="351.869249"
+ id="use2358" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 37.764612 35.581101 C 37.764612 36.05239 37.000354 36.434421 36.057776 36.434421 C 35.115198 36.434421 34.351136 36.05239 34.351136 35.581101 C 34.351136 35.109812 35.115198 34.727781 36.057776 34.727781 C 37.000354 34.727781 37.764612 35.109812 37.764612 35.581101 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2362" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;"
+ d="M 40.467932 33.267624 L 37.821448 34.655906 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2364" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 37.705237 34.434616 L 37.378675 34.888132 L 37.937659 34.87739 Z M 37.705237 34.434616 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2366" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 32.959534 35.587546 L 33.814417 35.585788 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2368" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 34.189417 35.585007 L 33.690003 35.835984 L 33.814417 35.585788 L 33.689026 35.335984 Z M 34.189417 35.585007 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2370" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 37.812268 35.570554 L 39.839807 35.558249 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2372" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 40.214807 35.555906 L 39.71637 35.808835 L 39.839807 35.558249 L 39.713245 35.308835 Z M 40.214807 35.555906 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2374" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 40.726721 34.542624 L 44.835315 34.542624 L 44.107386 36.542624 L 39.998792 36.542624 Z M 40.726721 34.542624 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2376" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2394">
+ <use
+ xlink:href="#glyph0-17"
+ x="330.019531"
+ y="342.48253"
+ id="use2378" />
+ <use
+ xlink:href="#glyph0-30"
+ x="338.075087"
+ y="342.48253"
+ id="use2380" />
+ <use
+ xlink:href="#glyph0-28"
+ x="346.130642"
+ y="342.48253"
+ id="use2382" />
+ <use
+ xlink:href="#glyph0-34"
+ x="351.130642"
+ y="342.48253"
+ id="use2384" />
+ <use
+ xlink:href="#glyph0-14"
+ x="356.963976"
+ y="342.48253"
+ id="use2386" />
+ <use
+ xlink:href="#glyph0-13"
+ x="365.019531"
+ y="342.48253"
+ id="use2388" />
+ <use
+ xlink:href="#glyph0-34"
+ x="373.075087"
+ y="342.48253"
+ id="use2390" />
+ <use
+ xlink:href="#glyph0-29"
+ x="378.90842"
+ y="342.48253"
+ id="use2392" />
+ </g>
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 50.59469 35.581101 C 50.59469 36.05239 49.830432 36.434421 48.887854 36.434421 C 47.945276 36.434421 47.181214 36.05239 47.181214 35.581101 C 47.181214 35.109812 47.945276 34.727781 48.887854 34.727781 C 49.830432 34.727781 50.59469 35.109812 50.59469 35.581101 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2396" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;"
+ d="M 54.927893 33.267624 L 50.860901 34.825437 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2398" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 50.771643 34.591843 L 50.394104 35.004148 L 50.950354 35.058835 Z M 50.771643 34.591843 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2400" />
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 44.49762 35.554929 L 46.650745 35.56782 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2402" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 47.025745 35.569968 L 46.524182 35.817038 L 46.650745 35.56782 L 46.527307 35.317038 Z M 47.025745 35.569968 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2404" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%,70.19608%,14.509805%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 54.63805 34.542624 L 61.1693 34.542624 L 60.44137 36.542624 L 53.91012 36.542624 Z M 54.63805 34.542624 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2406" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2426">
+ <use
+ xlink:href="#glyph0-17"
+ x="628.445313"
+ y="342.48253"
+ id="use2408" />
+ <use
+ xlink:href="#glyph0-13"
+ x="636.500868"
+ y="342.48253"
+ id="use2410" />
+ <use
+ xlink:href="#glyph0-20"
+ x="644.556424"
+ y="342.48253"
+ id="use2412" />
+ <use
+ xlink:href="#glyph0-28"
+ x="652.611979"
+ y="342.48253"
+ id="use2414" />
+ <use
+ xlink:href="#glyph0-34"
+ x="657.611979"
+ y="342.48253"
+ id="use2416" />
+ <use
+ xlink:href="#glyph0-14"
+ x="663.445313"
+ y="342.48253"
+ id="use2418" />
+ <use
+ xlink:href="#glyph0-13"
+ x="671.500868"
+ y="342.48253"
+ id="use2420" />
+ <use
+ xlink:href="#glyph0-34"
+ x="679.556424"
+ y="342.48253"
+ id="use2422" />
+ <use
+ xlink:href="#glyph0-29"
+ x="685.389757"
+ y="342.48253"
+ id="use2424" />
+ </g>
+ <path
+ style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 50.577698 35.573484 L 53.753479 35.559421 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2428" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;"
+ d="M 54.128479 35.557663 L 53.629651 35.810007 L 53.753479 35.559421 L 53.627503 35.310007 Z M 54.128479 35.557663 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2430" />
+ <path
+ style="fill-rule:evenodd;fill:rgb(100%, 100%, 100%);fill-opacity:1;stroke-width:0.20012599;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%, 0%, 0%);stroke-opacity:1;stroke-miterlimit:10;stroke-dasharray:none"
+ d="M 24.669495 38.169382 L 66.289417 38.169382 L 66.289417 40.751023 L 24.669495 40.751023 Z M 24.669495 38.169382 "
+ transform="matrix(20,0,0,20,-491.389899,-372.25483)"
+ id="path2432" />
+ <g
+ style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+ id="g2574">
+ <use
+ xlink:href="#glyph1-1"
+ x="13.492188"
+ y="422.957954"
+ id="use2434" />
+ <use
+ xlink:href="#glyph1-2"
+ x="27.658854"
+ y="422.957954"
+ id="use2436" />
+ <use
+ xlink:href="#glyph1-3"
+ x="41.825521"
+ y="422.957954"
+ id="use2438" />
+ <use
+ xlink:href="#glyph1-4"
+ x="49.325521"
+ y="422.957954"
+ id="use2440" />
+ <use
+ xlink:href="#glyph1-5"
+ x="62.658854"
+ y="422.957954"
+ id="use2442" />
+ <use
+ xlink:href="#glyph1-5"
+ x="72.381076"
+ y="422.957954"
+ id="use2444" />
+ <use
+ xlink:href="#glyph1-4"
+ x="82.103299"
+ y="422.957954"
+ id="use2446" />
+ <use
+ xlink:href="#glyph1-6"
+ x="94.881076"
+ y="422.957954"
+ id="use2448" />
+ <use
+ xlink:href="#glyph1-7"
+ x="107.658854"
+ y="422.957954"
+ id="use2450" />
+ <use
+ xlink:href="#glyph1-8"
+ x="116.825521"
+ y="422.957954"
+ id="use2452"
+ style="fill:#9ca1f8;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-9"
+ x="130.436632"
+ y="422.957954"
+ id="use2454"
+ style="fill:#9ca1f8;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-10"
+ x="144.047743"
+ y="422.957954"
+ id="use2456" />
+ <use
+ xlink:href="#glyph1-11"
+ x="151.547743"
+ y="422.957954"
+ id="use2458" />
+ <use
+ xlink:href="#glyph1-12"
+ x="158.492188"
+ y="422.957954"
+ id="use2460" />
+ <use
+ xlink:href="#glyph1-13"
+ x="172.658854"
+ y="422.957954"
+ id="use2462" />
+ <use
+ xlink:href="#glyph1-6"
+ x="182.103299"
+ y="422.957954"
+ id="use2464" />
+ <use
+ xlink:href="#glyph1-2"
+ x="194.881076"
+ y="422.957954"
+ id="use2466" />
+ <use
+ xlink:href="#glyph1-14"
+ x="209.047743"
+ y="422.957954"
+ id="use2468" />
+ <use
+ xlink:href="#glyph1-15"
+ x="222.381076"
+ y="422.957954"
+ id="use2470" />
+ <use
+ xlink:href="#glyph1-16"
+ x="239.047743"
+ y="422.957954"
+ id="use2472"
+ style="fill:#9ca1f8;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-1"
+ x="245.71441"
+ y="422.957954"
+ id="use2474"
+ style="fill:#9ca1f8;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-13"
+ x="259.881076"
+ y="422.957954"
+ id="use2476"
+ style="fill:#9ca1f8;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-9"
+ x="269.325521"
+ y="422.957954"
+ id="use2478"
+ style="fill:#9ca1f8;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-8"
+ x="282.936632"
+ y="422.957954"
+ id="use2480"
+ style="fill:#9ca1f8;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-17"
+ x="296.547743"
+ y="422.957954"
+ id="use2482" />
+ <use
+ xlink:href="#glyph1-3"
+ x="305.71441"
+ y="422.957954"
+ id="use2484" />
+ <use
+ xlink:href="#glyph1-4"
+ x="313.21441"
+ y="422.957954"
+ id="use2486" />
+ <use
+ xlink:href="#glyph1-18"
+ x="326.547743"
+ y="422.957954"
+ id="use2488" />
+ <use
+ xlink:href="#glyph1-13"
+ x="338.21441"
+ y="422.957954"
+ id="use2490" />
+ <use
+ xlink:href="#glyph1-6"
+ x="347.658854"
+ y="422.957954"
+ id="use2492" />
+ <use
+ xlink:href="#glyph1-2"
+ x="360.436632"
+ y="422.957954"
+ id="use2494" />
+ <use
+ xlink:href="#glyph1-14"
+ x="374.603299"
+ y="422.957954"
+ id="use2496" />
+ <use
+ xlink:href="#glyph1-7"
+ x="387.936632"
+ y="422.957954"
+ id="use2498" />
+ <use
+ xlink:href="#glyph1-19"
+ x="397.103299"
+ y="422.957954"
+ id="use2500"
+ style="fill:#000000;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-20"
+ x="407.381076"
+ y="422.957954"
+ id="use2502"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-9"
+ x="421.547743"
+ y="422.957954"
+ id="use2504"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-21"
+ x="435.158854"
+ y="422.957954"
+ id="use2506"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-19"
+ x="448.769965"
+ y="422.957954"
+ id="use2508"
+ style="fill:#000000;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-17"
+ x="459.047743"
+ y="422.957954"
+ id="use2510" />
+ <use
+ xlink:href="#glyph1-11"
+ x="468.21441"
+ y="422.957954"
+ id="use2512" />
+ <use
+ xlink:href="#glyph1-11"
+ x="475.158854"
+ y="422.957954"
+ id="use2514" />
+ <use
+ xlink:href="#glyph1-22"
+ x="482.103299"
+ y="422.957954"
+ id="use2516" />
+ <use
+ xlink:href="#glyph1-11"
+ x="498.769965"
+ y="422.957954"
+ id="use2518" />
+ <use
+ xlink:href="#glyph1-1"
+ x="505.71441"
+ y="422.957954"
+ id="use2520" />
+ <use
+ xlink:href="#glyph1-2"
+ x="519.881076"
+ y="422.957954"
+ id="use2522" />
+ <use
+ xlink:href="#glyph1-3"
+ x="534.047743"
+ y="422.957954"
+ id="use2524" />
+ <use
+ xlink:href="#glyph1-4"
+ x="541.547743"
+ y="422.957954"
+ id="use2526" />
+ <use
+ xlink:href="#glyph1-5"
+ x="554.881076"
+ y="422.957954"
+ id="use2528" />
+ <use
+ xlink:href="#glyph1-5"
+ x="564.603299"
+ y="422.957954"
+ id="use2530" />
+ <use
+ xlink:href="#glyph1-4"
+ x="574.325521"
+ y="422.957954"
+ id="use2532" />
+ <use
+ xlink:href="#glyph1-6"
+ x="587.103299"
+ y="422.957954"
+ id="use2534" />
+ <use
+ xlink:href="#glyph1-7"
+ x="599.881076"
+ y="422.957954"
+ id="use2536" />
+ <use
+ xlink:href="#glyph1-19"
+ x="609.047743"
+ y="422.957954"
+ id="use2538"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-8"
+ x="619.325521"
+ y="422.957954"
+ id="use2540"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-9"
+ x="632.936632"
+ y="422.957954"
+ id="use2542"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-19"
+ x="646.547743"
+ y="422.957954"
+ id="use2544"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-10"
+ x="656.825521"
+ y="422.957954"
+ id="use2546" />
+ <use
+ xlink:href="#glyph1-11"
+ x="664.325521"
+ y="422.957954"
+ id="use2548" />
+ <use
+ xlink:href="#glyph1-12"
+ x="671.269965"
+ y="422.957954"
+ id="use2550" />
+ <use
+ xlink:href="#glyph1-13"
+ x="685.436632"
+ y="422.957954"
+ id="use2552" />
+ <use
+ xlink:href="#glyph1-6"
+ x="694.881076"
+ y="422.957954"
+ id="use2554" />
+ <use
+ xlink:href="#glyph1-2"
+ x="707.658854"
+ y="422.957954"
+ id="use2556" />
+ <use
+ xlink:href="#glyph1-14"
+ x="721.825521"
+ y="422.957954"
+ id="use2558" />
+ <use
+ xlink:href="#glyph1-15"
+ x="735.158854"
+ y="422.957954"
+ id="use2560" />
+ <use
+ xlink:href="#glyph1-19"
+ x="751.825521"
+ y="422.957954"
+ id="use2562" />
+ <use
+ xlink:href="#glyph1-20"
+ x="762.103299"
+ y="422.957954"
+ id="use2564"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-9"
+ x="776.269965"
+ y="422.957954"
+ id="use2566"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-21"
+ x="789.881076"
+ y="422.957954"
+ id="use2568"
+ style="fill:#ffb323;fill-opacity:1" />
+ <use
+ xlink:href="#glyph1-19"
+ x="803.492188"
+ y="422.957954"
+ id="use2570" />
+ <use
+ xlink:href="#glyph1-17"
+ x="813.769965"
+ y="422.957954"
+ id="use2572" />
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:14.6266px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;stroke:#cccccc;stroke-width:0.483685"
+ x="61.029861"
+ y="206.28314"
+ id="text2605"><tspan
+ sodipodi:role="line"
+ id="tspan2603"
+ x="61.029861"
+ y="206.28314"
+ style="stroke:#cccccc;stroke-width:0.483685">cast not required</tspan></text>
+ <text
+ id="text2609"
+ y="127.66325"
+ x="395.55035"
+ style="font-size:14.6266px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;stroke:#cccccc;stroke-width:0.483685"
+ xml:space="preserve"><tspan
+ style="stroke:#cccccc;stroke-width:0.483685"
+ y="127.66325"
+ x="395.55035"
+ id="tspan2607"
+ sodipodi:role="line">only implements S8</tspan></text>
+ </g>
+</svg>
diff --git a/doc/neps/_static/dtype_hierarchy.svg b/doc/neps/_static/dtype_hierarchy.svg
new file mode 100644
index 000000000..3bade3d0f
--- /dev/null
+++ b/doc/neps/_static/dtype_hierarchy.svg
@@ -0,0 +1,935 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="432.64694mm"
+ height="374.31384mm"
+ viewBox="0 0 432.64693 374.31384"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="dtype_hierarchy.svg"
+ inkscape:export-filename="/home/sebastian/BIDS/dtypes/dtype_hierarchy.png"
+ inkscape:export-xdpi="43.502129"
+ inkscape:export-ydpi="43.502129">
+ <defs
+ id="defs2">
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker1380"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Mend">
+ <path
+ transform="scale(-0.6)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path1378"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mstart"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path835"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+ transform="matrix(0.4,0,0,0.4,4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible"
+ inkscape:isstock="true"
+ inkscape:collect="always">
+ <path
+ id="path856"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Send"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path844"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path832"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.49497475"
+ inkscape:cx="-261.18562"
+ inkscape:cy="440.75659"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="3440"
+ inkscape:window-height="1376"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ fit-margin-top="10"
+ fit-margin-left="10"
+ fit-margin-right="10"
+ fit-margin-bottom="10" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(1.2604327,40.771063)">
+ <rect
+ style="opacity:1;fill:#ff9000;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2120"
+ width="44.63401"
+ height="17.105249"
+ x="23.573442"
+ y="161.07759"
+ rx="2.843874"
+ ry="2.5766025" />
+ <text
+ id="text2124"
+ y="172.67239"
+ x="30.910395"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
+ y="172.67239"
+ x="30.910395"
+ id="tspan2122"
+ sodipodi:role="line">DType</tspan></text>
+ <g
+ id="g1288">
+ <rect
+ style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2146"
+ width="61.739262"
+ height="17.105249"
+ x="42.09428"
+ y="203.41173"
+ rx="2.843874"
+ ry="2.5766025" />
+ <text
+ id="text2150"
+ y="215.00667"
+ x="56.400177"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="215.00667"
+ x="56.400177"
+ id="tspan2148"
+ sodipodi:role="line">Float64</tspan></text>
+ </g>
+ <g
+ id="g1283">
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="182.24493"
+ x="42.09428"
+ height="17.105249"
+ width="61.739262"
+ id="rect2154"
+ style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="61.425056"
+ y="194.36903"
+ id="text2158"><tspan
+ sodipodi:role="line"
+ id="tspan2156"
+ x="61.425056"
+ y="194.36903"
+ style="stroke-width:0.26458332">Int64</tspan></text>
+ </g>
+ <g
+ id="g1334"
+ transform="translate(46.037524,104.2459)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path827"
+ d="m 58.264755,86.658881 h 10.69078"
+ style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ transform="translate(25.819071,143.16003)"
+ id="g2205">
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2199"
+ width="44.63401"
+ height="17.105249"
+ x="92.475258"
+ y="39.0849"
+ rx="0"
+ ry="0" />
+ <text
+ id="text2203"
+ y="50.67984"
+ x="99.81221"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="50.67984"
+ x="99.81221"
+ id="tspan2201"
+ sodipodi:role="line">&gt;int64</tspan></text>
+ </g>
+ <g
+ id="g2213"
+ transform="translate(75.560923,143.16003)">
+ <rect
+ ry="0"
+ rx="0"
+ y="39.0849"
+ x="92.475258"
+ height="17.105249"
+ width="44.63401"
+ id="rect2207"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="99.81221"
+ y="50.67984"
+ id="text2211"><tspan
+ sodipodi:role="line"
+ id="tspan2209"
+ x="99.81221"
+ y="50.67984"
+ style="stroke-width:0.26458332">&lt;int64</tspan></text>
+ </g>
+ <g
+ id="g2663"
+ transform="translate(-50.910137,157.97679)">
+ <g
+ id="g2645"
+ transform="translate(96.947661,-32.563904)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path2643"
+ d="m 58.264755,86.658881 h 10.69078"
+ style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ transform="translate(76.729209,6.3500001)"
+ id="g2653">
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2647"
+ width="44.63401"
+ height="17.105249"
+ x="92.475258"
+ y="39.0849"
+ rx="0"
+ ry="0" />
+ <text
+ id="text2651"
+ y="50.67984"
+ x="97.166374"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="50.67984"
+ x="97.166374"
+ id="tspan2649"
+ sodipodi:role="line">&gt;float64</tspan></text>
+ </g>
+ <g
+ id="g2661"
+ transform="translate(126.47106,6.3500001)">
+ <rect
+ ry="0"
+ rx="0"
+ y="39.0849"
+ x="92.475258"
+ height="17.105249"
+ width="44.63401"
+ id="rect2655"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="96.637207"
+ y="50.67984"
+ id="text2659"><tspan
+ sodipodi:role="line"
+ id="tspan2657"
+ x="96.637207"
+ y="50.67984"
+ style="stroke-width:0.26458332">&lt;float64</tspan></text>
+ </g>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.51278019px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="146.93526"
+ y="178.48193"
+ id="text2737"><tspan
+ sodipodi:role="line"
+ id="tspan2735"
+ x="146.93526"
+ y="178.48193"
+ style="fill:#9866cf;fill-opacity:1;stroke-width:0.26458332">Instances</tspan></text>
+ <text
+ id="text2675-3"
+ y="153.10063"
+ x="8.1723146"
+ style="font-style:normal;font-weight:normal;font-size:11.38954353px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.26458329"
+ y="153.10063"
+ x="8.1723146"
+ id="tspan2673-6"
+ sodipodi:role="line">Concrete Types:</tspan></text>
+ <text
+ id="text3215"
+ y="72.108665"
+ x="243.3298"
+ style="font-style:normal;font-weight:normal;font-size:8.51278019px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="fill:#9866cf;fill-opacity:1;stroke-width:0.26458332"
+ y="72.108665"
+ x="243.3298"
+ id="tspan3213"
+ sodipodi:role="line">Instances</tspan></text>
+ <g
+ id="g1293">
+ <rect
+ style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2146-6"
+ width="61.739262"
+ height="17.105249"
+ x="42.297195"
+ y="224.75034"
+ rx="2.843874"
+ ry="2.5766025" />
+ <text
+ id="text2150-7"
+ y="236.34528"
+ x="47.843731"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="236.34528"
+ x="47.843731"
+ id="tspan2148-5"
+ sodipodi:role="line">datetime64</tspan></text>
+ </g>
+ <g
+ transform="translate(-50.910137,179.14359)"
+ id="g1057">
+ <g
+ transform="translate(96.947661,-32.563904)"
+ id="g1039">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 58.264755,86.658881 h 10.69078"
+ id="path1037"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g1047"
+ transform="translate(76.729209,6.3500001)">
+ <rect
+ ry="0"
+ rx="0"
+ y="39.0849"
+ x="92.475258"
+ height="17.105249"
+ width="44.63401"
+ id="rect1041"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="98.777588"
+ y="50.67984"
+ id="text1045"><tspan
+ sodipodi:role="line"
+ id="tspan1043"
+ x="98.777588"
+ y="50.67984"
+ style="stroke-width:0.26458332">&lt;M8[s]</tspan></text>
+ </g>
+ <g
+ transform="translate(126.47106,6.3500001)"
+ id="g1055">
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1049"
+ width="44.63401"
+ height="17.105249"
+ x="92.475258"
+ y="39.0849"
+ rx="0"
+ ry="0" />
+ <text
+ id="text1053"
+ y="50.67984"
+ x="96.000237"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="50.67984"
+ x="96.000237"
+ id="tspan1051"
+ sodipodi:role="line">&gt;M8[ns]</tspan></text>
+ <rect
+ ry="0"
+ rx="0"
+ y="39.0849"
+ x="92.475258"
+ height="17.105249"
+ width="44.63401"
+ id="rect1207"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ id="g1265"
+ style="fill:#9866cf;fill-opacity:1"
+ transform="matrix(2.2707534,0,0,2.2707534,-177.4572,-60.535544)">
+ <circle
+ r="1.1358955"
+ cy="47.637524"
+ cx="141.20377"
+ id="path1256"
+ style="opacity:1;fill:#9866cf;fill-opacity:1;stroke:none;stroke-width:1.71979165;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <circle
+ style="opacity:1;fill:#9866cf;fill-opacity:1;stroke:none;stroke-width:1.71979165;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="circle1258"
+ cx="144.21054"
+ cy="47.637524"
+ r="1.1358955" />
+ <circle
+ r="1.1358955"
+ cy="47.637524"
+ cx="147.21733"
+ id="circle1260"
+ style="opacity:1;fill:#9866cf;fill-opacity:1;stroke:none;stroke-width:1.71979165;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.38954353px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329"
+ x="8.1723146"
+ y="-22.317886"
+ id="text2802"><tspan
+ sodipodi:role="line"
+ id="tspan2800"
+ x="8.1723146"
+ y="-22.317886"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.26458329">Concept:</tspan></text>
+ <ellipse
+ ry="11.626225"
+ rx="29.800554"
+ cy="-4.7734947"
+ cx="53.874973"
+ id="path2804"
+ style="opacity:1;fill:#ffc553;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
+ x="28.792381"
+ y="-2.5054595"
+ id="text2808"><tspan
+ sodipodi:role="line"
+ id="tspan2806"
+ x="28.792381"
+ y="-2.5054595"
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1">DTypeMeta</tspan></text>
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="-14.100398"
+ x="96.558197"
+ height="17.105249"
+ width="44.63401"
+ id="rect2810"
+ style="opacity:1;fill:#ff9000;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
+ x="104.69695"
+ y="-3.0399978"
+ id="text2814"><tspan
+ sodipodi:role="line"
+ id="tspan2812"
+ x="104.69695"
+ y="-3.0399978"
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1">DType</tspan></text>
+ <g
+ transform="translate(25.655198,-91.784983)"
+ id="g2818">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 58.264755,86.658881 h 10.69078"
+ id="path2816"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g2846"
+ transform="translate(4.3286934,-30.623148)">
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="39.0849"
+ x="108.87944"
+ height="52.384823"
+ width="90.871613"
+ id="rect2840"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="112.0525"
+ y="50.851093"
+ id="text2844"><tspan
+ id="tspan2842"
+ sodipodi:role="line"
+ x="112.0525"
+ y="50.851093"
+ style="stroke-width:0.26458332">AbstractDtypes:</tspan><tspan
+ sodipodi:role="line"
+ x="112.0525"
+ y="62.140648"
+ style="stroke-width:0.26458332"
+ id="tspan3068">• type hierarchy</tspan><tspan
+ sodipodi:role="line"
+ x="112.0525"
+ y="73.430199"
+ style="stroke-width:0.26458332"
+ id="tspan3078">• UFunc resolution</tspan><tspan
+ sodipodi:role="line"
+ x="112.0525"
+ y="84.719757"
+ style="stroke-width:0.26458332"
+ id="tspan3072">• may promote</tspan><tspan
+ sodipodi:role="line"
+ x="112.0525"
+ y="96.009308"
+ style="stroke-width:0.26458332"
+ id="tspan3066" /></text>
+ </g>
+ <g
+ transform="translate(20.732865,35.976636)"
+ id="g2854">
+ <rect
+ style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2848"
+ width="91.940727"
+ height="47.306705"
+ x="92.475258"
+ y="39.0849"
+ rx="2.843874"
+ ry="2.5766025" />
+ <text
+ id="text2852"
+ y="49.872658"
+ x="96.583473"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="49.872658"
+ x="96.583473"
+ id="tspan2850"
+ sodipodi:role="line">Concrete DTypes:</tspan><tspan
+ style="stroke-width:0.26458332"
+ y="60.811176"
+ x="96.583473"
+ sodipodi:role="line"
+ id="tspan3086">• casting/promotion</tspan><tspan
+ style="stroke-width:0.26458332"
+ y="71.749695"
+ x="96.583473"
+ sodipodi:role="line"
+ id="tspan3088">• UFunc signature</tspan></text>
+ </g>
+ <g
+ transform="translate(148.727,10.030009)"
+ id="g2858">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 58.264755,86.658881 h 10.69078"
+ id="path2856"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2860"
+ width="84.724449"
+ height="45.435818"
+ x="220.98373"
+ y="75.328812"
+ rx="0"
+ ry="0" />
+ <text
+ id="text2864"
+ y="86.923752"
+ x="228.32069"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="86.923752"
+ x="228.32069"
+ id="tspan2862"
+ sodipodi:role="line">DType Instances</tspan><tspan
+ id="tspan3074"
+ style="stroke-width:0.26458332"
+ y="97.862267"
+ x="228.32069"
+ sodipodi:role="line">• Describe data</tspan><tspan
+ id="tspan3076"
+ style="stroke-width:0.26458332"
+ y="108.80079"
+ x="228.32069"
+ sodipodi:role="line">• `arr.dtype`</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="228.32069"
+ y="38.240372"
+ id="text3096"><tspan
+ sodipodi:role="line"
+ x="228.32069"
+ y="38.240372"
+ style="stroke-width:0.26458332"
+ id="tspan3094">(Cannot be instantiated)</tspan></text>
+ <text
+ id="text3223"
+ y="277.53149"
+ x="163.20908"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ id="tspan3221"
+ style="stroke-width:0.26458332"
+ y="277.53149"
+ x="163.20908"
+ sodipodi:role="line">Concrete Types form</tspan><tspan
+ style="stroke-width:0.26458332"
+ y="288.47"
+ x="163.20908"
+ sodipodi:role="line"
+ id="tspan3225">leaves of the tree;</tspan><tspan
+ id="tspan3248"
+ style="stroke-width:0.26458332"
+ y="299.40854"
+ x="163.20908"
+ sodipodi:role="line">the inheritance is abstract</tspan><tspan
+ id="tspan3270"
+ style="stroke-width:0.26458332"
+ y="310.34705"
+ x="163.20908"
+ sodipodi:role="line">similar to Python's abc.ABC. </tspan></text>
+ <g
+ id="g3084"
+ transform="translate(35.454183,8.4666671)">
+ <g
+ transform="translate(111.41246,-60.58556)"
+ id="g3058">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 58.264755,86.658881 h 10.69078"
+ id="path3056"
+ inkscape:connector-curvature="0" />
+ </g>
+ <text
+ id="text3062"
+ y="33.375549"
+ x="177.81163"
+ style="font-style:normal;font-weight:normal;font-size:25.73707581px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="33.375549"
+ x="177.81163"
+ id="tspan3060"
+ sodipodi:role="line">x</tspan></text>
+ </g>
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path3217"
+ d="m 240.37519,140.22719 v 115.49978 l -21.73363,-0.0959"
+ style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 373.75879,132.43914 H 41.810036"
+ id="path3219"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g1383"
+ transform="translate(1.5875)">
+ <g
+ transform="translate(282.50926,124.19261)"
+ id="g1309">
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="182.24493"
+ x="42.09428"
+ height="17.105249"
+ width="61.739262"
+ id="rect1303"
+ style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="61.425056"
+ y="194.36903"
+ id="text1307"><tspan
+ sodipodi:role="line"
+ id="tspan1305"
+ x="61.425056"
+ y="194.36903"
+ style="stroke-width:0.26458332">Int64</tspan></text>
+ </g>
+ <g
+ transform="translate(283.57834,60.501707)"
+ id="g1301">
+ <rect
+ style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1295"
+ width="61.739262"
+ height="17.105249"
+ x="42.09428"
+ y="203.41173"
+ rx="2.843874"
+ ry="2.5766025" />
+ <text
+ id="text1299"
+ y="215.00667"
+ x="56.400177"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="215.00667"
+ x="56.400177"
+ id="tspan1297"
+ sodipodi:role="line">Float64</tspan></text>
+ </g>
+ <g
+ transform="translate(185.91751,182.30441)"
+ id="g2195">
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2187"
+ width="44.63401"
+ height="17.105249"
+ x="108.87944"
+ y="39.0849"
+ rx="2.843874"
+ ry="2.5766025" />
+ <text
+ id="text2193"
+ y="50.321926"
+ x="113.11084"
+ style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="50.321926"
+ x="113.11084"
+ sodipodi:role="line"
+ id="tspan2191">Inexact</tspan></text>
+ </g>
+ <g
+ id="g2671"
+ transform="translate(172.15917,161.04236)">
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="39.0849"
+ x="108.87944"
+ height="17.105249"
+ width="44.63401"
+ id="rect2665"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="112.0525"
+ y="50.851093"
+ id="text2669"><tspan
+ id="tspan2667"
+ sodipodi:role="line"
+ x="112.0525"
+ y="50.851093"
+ style="stroke-width:0.26458332">Numeric</tspan></text>
+ </g>
+ <g
+ id="g2701"
+ transform="translate(170.57168,118.51826)">
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="39.0849"
+ x="92.475258"
+ height="17.105249"
+ width="44.63401"
+ id="rect2695"
+ style="opacity:1;fill:#ff9153;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="99.81221"
+ y="50.67984"
+ id="text2699"><tspan
+ sodipodi:role="line"
+ id="tspan2697"
+ x="99.81221"
+ y="50.67984"
+ style="stroke-width:0.26458332">DType</tspan></text>
+ </g>
+ <g
+ id="g2709"
+ transform="translate(201.26335,203.56648)">
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="39.0849"
+ x="108.87944"
+ height="17.105249"
+ width="44.63401"
+ id="rect2703"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="112.0525"
+ y="50.321926"
+ id="text2707"><tspan
+ id="tspan2705"
+ sodipodi:role="line"
+ x="112.0525"
+ y="50.321926"
+ style="stroke-width:0.26458332">Floating</tspan></text>
+ </g>
+ <g
+ id="g2717"
+ transform="translate(185.38297,221.7489)">
+ <rect
+ ry="2.5766025"
+ rx="2.843874"
+ y="63.42659"
+ x="108.87944"
+ height="17.105249"
+ width="44.63401"
+ id="rect2711"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="113.11084"
+ y="74.663612"
+ id="text2715"><tspan
+ id="tspan2713"
+ sodipodi:role="line"
+ x="113.11084"
+ y="74.663612"
+ style="stroke-width:0.26458332">Integral</tspan></text>
+ </g>
+ <text
+ id="text2774"
+ y="149.89339"
+ x="244.4957"
+ style="font-style:normal;font-weight:normal;font-size:11.38954258px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.26458329"
+ y="149.89339"
+ x="244.4957"
+ id="tspan2772"
+ sodipodi:role="line">Abstract Types (Hierarchy):</tspan></text>
+ <g
+ transform="translate(238.74141,-45.88513)"
+ id="g1317">
+ <rect
+ style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1311"
+ width="61.739262"
+ height="17.105249"
+ x="42.297195"
+ y="224.75034"
+ rx="2.843874"
+ ry="2.5766025" />
+ <text
+ id="text1315"
+ y="236.34528"
+ x="47.843731"
+ style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ xml:space="preserve"><tspan
+ style="stroke-width:0.26458332"
+ y="236.34528"
+ x="47.843731"
+ id="tspan1313"
+ sodipodi:role="line">datetime64</tspan></text>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/neps/nep-0029-deprecation_policy.rst b/doc/neps/nep-0029-deprecation_policy.rst
index 9b6022a81..dbead1b9b 100644
--- a/doc/neps/nep-0029-deprecation_policy.rst
+++ b/doc/neps/nep-0029-deprecation_policy.rst
@@ -1,4 +1,4 @@
-.. _NEP0029:
+.. _NEP29:
==================================================================================
NEP 29 — Recommend Python and Numpy version support as a community policy standard
diff --git a/doc/neps/nep-0042-new-dtypes.rst b/doc/neps/nep-0042-new-dtypes.rst
new file mode 100644
index 000000000..1c44c68ea
--- /dev/null
+++ b/doc/neps/nep-0042-new-dtypes.rst
@@ -0,0 +1,1330 @@
+========================================
+NEP 42 — Implementation of New DataTypes
+========================================
+
+:title: Extensible Datatypes for NumPy
+:Author: Sebastian Berg
+:Status: Draft
+:Type: Standard
+:Created: 2019-07-17
+
+
+.. note::
+
+ This NEP is part of a series of NEPs encompassing first information
+ about the previous dtype implementation and issues with it in
+ :ref:`NEP 40 <NEP40>`.
+ :ref:`NEP 41 <NEP41>` then provides an overview and generic design
+ choices for the refactor. NEPs 42 (this document)
+ and 43 go into the technical details of the internal and external
+ API changes related to datatypes and universal functions, respectively.
+ In some cases it may be necessary to consult the other NEPs for a full
+ picture of the desired changes and why these changes are necessary.
+
+
+Abstract
+--------
+
+NEP 40 and 41 detailed the need for the creation of a new datatype system within
+NumPy to better serve downstream use-cases and improve the maintainability
+and the extensibility of NumPy.
+A main issue with the current dtype API is that datatypes are written as
+a single Python class with special instances for each of the actual datatypes.
+While this certainly has been a practical approach in implementing numerical
+datatypes, it does not allow to naturally split up logic. For example,
+functions such as ``can_cast`` have explicit logic for each datatype.
+Because of this monolithic code structure user-defined datatypes do not have
+the same capabilities as NumPy datatypes have.
+The current structure also makes understanding and modifying datatypes harder.
+The current datatypes are not well encapsulated, so modifications targeting
+a single datatype inevitably touch code involving others.
+As detailed in NEP 41, the desired general design is to create classes for
+each of the NumPy-provided datatypes, meaning that ``np.dtype("float64")``
+returns an instance of a ``Float64`` class which is a subclass of ``np.dtype``.
+``np.dtype[float64]`` will also be used to denote this class.
+This will allow moving all logic into special methods on the ``np.dtype``
+subclasses. This ``DType`` class would then serve as the central
+extension point for adding new dtypes to NumPy.
+
+This document proposes the new API for the datatypes itself.
+A second proposal NEP 43 details proposed changes to the universal
+functions.
+Note that only the implementation of both NEPs will provide the desired full
+functionality.
+
+
+.. note::
+
+ At this time this NEP is in a preliminary state. Both internal and
+ external API may be adapted based on user input or implementation needs.
+ The general design principles and choices, while provisional, should not
+ be expected to change dramatically.
+
+
+Detailed Description
+--------------------
+
+NEP 41 layed out the creation of a class hierarchy for datatypes using the
+new DType classes to provide all necessary implementations.
+This NEP defines the specific choice of API necessary to define new DTypes.
+Here, these are suggested as C-API slots; however, conceptually these
+translate identically to Python methods.
+
+Additionally, the NEP proposes to implement the notion of *abstract* DTypes.
+Further, we detail – in part – how the proposed methods (C-API slots)
+enable all necessary use cases.
+
+Each section will begin with a short motivation of the issue or what
+problem is addressed. This is followed by a description of the proposed
+design choice, and then may list alternatives.
+
+
+Nomenclature
+""""""""""""
+
+As a brief note on nomenclature, it should be noted that ``dtype`` normally
+denotes the dtype *instance*, which is the object attached to a numpy array.
+On the other hand the ``DType`` class is the subclass of ``np.dtype``.
+On the C-level we currently use the name ``descriptor`` or ``descr``
+interchangeably with *dtype instance*. ``descriptor`` or ``descr`` will be
+used in proposed C-API names to differentiate dtype instances from DType
+classes more clearly.
+Note that the notion of dtype class is currently represented mainly as
+the ``dtype.num`` and ``dtype.char``.
+Please see the `dtype hierarchy figure <hierarchy_figure>`_ for an
+illustration of this distinction.
+
+There are currently classes in NumPy for numeric types e.g.
+``np.float64``; however,
+these are not DTypes but the corresponding scalar classes
+(see also NEP 40 and 41 for discussion on why these are largely unrelated to
+the proposed changes).
+
+
+Proposed access to DType class
+""""""""""""""""""""""""""""""
+
+**Motivation:**
+
+Currently we often call ``np.dtype`` to create the dtype instance
+corresponding to a given scalar type (e.g. ``np.dtype(np.int64)``).
+Adding the DType classes may require a way to access the classes conveniently.
+
+**Description:**
+
+To avoid duplication, but also to expose the classes conveniently to users
+we propose the addition of::
+
+ np.dtype[np.int64]
+
+as a class getter. This can work both for user and NumPy DTypes,
+although, in many cases a library may choose to provide a more direct
+way to access the specific DType class.
+This method may initially be limited to concrete DTypes.
+The main reason for this choice is to provide a single
+clear and future-proof way to find the DType class given the
+Python (scalar) class.
+
+This should not be a common operation, so providing this class getter reduces
+the pressure of adding the new DType classes into the namespace.
+
+*Note: This is currently a possible extension and not yet decided.*
+
+
+Hierarchy of DTypes and Abstract DTypes
+"""""""""""""""""""""""""""""""""""""""
+
+**Motivation:**
+The creation of DType classes has already been decided in NEP 41.
+Here we discuss the notion of **abstract** DTypes.
+There are multiple reasons for this:
+
+1. It allows the definition of a class hierarchy, in principle allowing checks like
+ ``isinstance(np.dtype("float64"), np.inexact)``.
+ **This hierarchy may be a prerequisite to implementing dispatching
+ for universal functions (NEP 43)**
+2. Abstract DTypes can enable code such as
+ ``arr.astype(Complex)`` to express the desire to cast to a
+ complex data type of unspecified precision.
+3. It anticipates the creation of families of DTypes by users.
+ For example allowing the creation of an abstract ``Unit`` class with a concrete
+ ``Float64Unit``. In which case ``Unit(np.float64, "m")`` could be
+ identical to ``Float64Unit("m")``.
+
+A very concrete example is the current Pandas ``Categorical`` DType,
+which may benefit from abstraction to allow the differentiation of
+a categorical of integer values and one of general object values.
+The reason for this is that we may want to reject
+``common_dtype(CategoricalInt64, String)``, but accept
+``common_dtype(CategoricalObject, String)`` to be the ``object`` DType.
+The current Pandas ``Categorical`` DType combines both and must remain
+representable. The solution is thus to make ``Categorical`` abstract with
+the two subclasses ``CategoricalInt64`` and ``CategoricalObject``
+distinguishing the two.
+
+
+**Description:**
+
+The figure below shows the proposed datatype hierarchy.
+It should be noted that abstract DTypes are distinct in two ways:
+
+1. They do not have instances. Instantiating an abstract DType has to return
+ a concrete subclass or raise an error (default, and possibly enforced
+ initially).
+2. Unlike concrete DTypes, abstract DTypes can be superclasses, they may also
+ serve like Python's abstract base classes (ABC).
+ (It may be possible to simply use/inherit from Python ABCs.)
+
+These two rules are identical to the type choices made for example in the
+`Julia language <https://docs.julialang.org/en/v1/manual/types/#man-abstract-types-1>`_.
+It allows for the creation of a datatype hierarchy, but avoids issues with
+subclassing concrete DTypes directly.
+For example, logic such as ``can_cast`` does not cleanly inherit from a
+``Int64`` to a ``Datetime64`` even though the ``Datetime64`` could be seen
+as an integer with only a unit attached (and thus implemented as a subclass).
+
+The main consequence for the DType implementer is that concrete DTypes can
+never be subclasses of existing concrete DTypes.
+End-users would not notice or need to know about this distinction.
+However, subclassing may be a possible mechanism to extend the datatypes
+in the future to allow specialized implementations for existing dtypes
+such as a GPU float64 subclassing a NumPy float64.
+
+The combination of (initially) rejecting subclassing of concrete DTypes
+while allowing it for abstract ones allows the transparent definition of
+a class hierarchy, while avoiding potential issues with subclassing and
+especially inheritance.
+
+As a technical implementation detail: the DType class will require C-side
+storage of methods and additional information.
+This requires the creation of a ``DTypeMeta`` class.
+Each ``DType`` class is thus an instance of ``DTypeMeta`` with a well-defined
+and extensible interface.
+The end-user will not need to be aware of this.
+
+.. _hierarchy_figure:
+.. figure:: _static/dtype_hierarchy.svg
+ :figclass: align-center
+
+
+Methods/Slots defined for each DType
+""""""""""""""""""""""""""""""""""""
+
+NEP 41 detailed that all logic should be defined through special methods
+on the DTypes.
+This section will list a specific set of such methods (in the form of
+Python methods).
+The C-side equivalent slot signature will be summarized below after proposing
+the general C-API for defining new Datatypes.
+Note that while the slots are defined as special Python methods here, this is
+for the readers convenience and *not* meant to imply the identical exposure
+as a Python API.
+This will need to be proposed in a separate, later, NEP.
+
+Some of the methods may be similar or even reuse existing Python slots.
+User-defined DType classes are discouraged from defining or using Python's
+special slots without consulting the NumPy developers, in order to allow
+defining them later.
+For example ``dtype1 & dtype2`` could be a shorthand for
+``np.common_dtype(dtype1, dtype2)``, and comparisons should be defined mainly
+through casting logic.
+
+
+Additional Information
+^^^^^^^^^^^^^^^^^^^^^^
+
+In addition to the more detailed methods below, the following general
+information is currently provided and will be defined on the class:
+
+* ``cls.parametric`` (see also `NEP 40 <NEP40>`_):
+
+ * Parametric will be a flag in the (private) C-API. However, the
+ Python API will instead use a ``ParametricDType`` class from
+ which to inherit. (This is similar to Python's type flags, which include
+ flags for some basic subclasses such as subclasses of ``float`` or ``tuple``)
+ * This flag is mainly to simplify DType creation and casting and
+ allow for performance tweaks.
+ * DTypes which are not parametric must define a canonical dtype instance
+ which should be a singleton.
+ * Parametric dtypes require some additional methods (below).
+
+* ``self.canonical`` method (Alternative: new instance attribute)
+
+ * Instead of byteorder, we may want a ``canonical`` flag (reusing the
+ ISNBO flag – "is native byte order" seems possible here).
+ This flag signals that the data are stored in the default/canonical way.
+ In practice this is always an NBO check, but generalization should be possible.
+ A potential use-case is a complex-conjugated instance of Complex which
+ stores ``real - imag`` instead of ``real + imag`` and is thus not
+ the canonical storage.
+
+* ``ensure_canonical(self) -> dtype`` return a new dtype (or ``self``).
+ The returned dtype must have the ``canonical`` flag set.
+
+* ``DType.type`` is the associated scalar type. ``dtype.type`` will be a
+ class attribute and the current ``dtype.type`` field will be considered
+ deprecated. This may be relaxed if a use-case arises.
+
+Additionally, existing methods (and C-side fields) will be provided.
+However, the fields ``kind`` and and ``char`` will be set to ``\0``
+(NULL character) on the C-side.
+While discouraged, except for NumPy builtin types, ``kind`` both will return
+the ``__qualname__`` of the object to ensure uniqueness for all DTypes.
+(the replacement for ``kind`` will be to use ``isinstance`` checks).
+
+Another example of methods that should be moved to the DType class are the
+various sorting functions, which shall be implemented by defining a method:
+
+* ``dtype_get_sort_function(self, sortkind="stable") -> sortfunction``
+
+which must return ``NotImplemented`` if the given ``sortkind`` is not known.
+Similarly, any function implemented previously which cannot be removed will
+be implemented as a special method.
+Since these methods can be deprecated and new (renamed) replacements added,
+the API is not defined here and it is acceptable if it changes over time.
+
+For some of the current "methods" defined on the dtype, including sorting,
+a long term solution may be to instead create generalized ufuncs to provide
+the functionality.
+
+**Alternatives:**
+
+Some of these flags could be implemented by inheriting
+for example from a ``ParametricDType`` class. However, on the C-side as
+an implementation detail it seems simpler to provide a flag.
+This does not preclude the possibility of creating a ``ParametricDType``
+to Python to represent the same thing.
+
+**Example:**
+
+The ``datetime64`` DType is considered parametric, due to its unit, and
+unlike a float64 has no canonical representation. The associated ``type``
+is the ``np.datetime64`` scalar.
+
+
+**Issues and Details:**
+
+A potential DType such as ``Categorical`` will not be required to have a clear type
+associated with it. Instead, the ``type`` may be ``object`` and the
+categoircal's values are arbitrary objects.
+Unlike with well-defined scalars, this ``type`` cannot
+not be used for the dtype discovery necessary for coercion
+(compare section `DType Discovery during Array Coercion`_).
+
+
+Coercion to and from Python Objects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**Motivation:**
+
+When storing a single value in an array or taking it out of the array,
+it is necessary to coerce (convert) it to and from the low-level
+representation inside the array.
+
+**Description:**
+
+Coercing to and from Python scalars requires two to three methods:
+
+1. ``__dtype_setitem__(self, item_pointer, value)``
+2. ``__dtype_getitem__(self, item_pointer, base_obj) -> object``
+ The ``base_obj`` should be ignored normally, it is provided *only* for
+ memory management purposes, pointing to an object owning the data.
+ It exists only to allow support of structured datatypes with subarrays
+ within NumPy, which (currently) return views into the array.
+ The function returns an equivalent Python scalar (i.e. typically a NumPy
+ scalar).
+3. ``__dtype_get_pyitem__(self, item_pointer, base_obj) -> object``
+ (initially hidden for new-style user-defined datatypes, may be exposed
+ on user request). This corresponds to the ``arr.item()`` method which
+ is also used by ``arr.tolist()`` and returns e.g. Python floats instead of
+ NumPy floats.
+
+(The above is meant for C-API. A Python-side API would have to use byte
+buffers or similar to implement this, which may be useful for prototyping.)
+
+These largely correspond to the current definitions. When a certain scalar
+has a known (different) dtype, NumPy may in the future use casting instead
+of ``__dtype_setitem__``.
+A user datatype is (initially) expected to implement ``__dtype_setitem__``
+for its own ``DType.type`` and all basic Python scalars it wishes to support
+(e.g. integers, floats, datetime).
+In the future a function "``known_scalartype``" may be added to allow a user
+dtype to signal which Python scalars it can store directly.
+
+
+**Implementation:**
+
+The pseudo-code implementation for setting a single item in an array
+from an arbitrary Python object ``value`` is (note that some of the
+functions are only defined below)::
+
+ def PyArray_Pack(dtype, item_pointer, value):
+ DType = type(dtype)
+ if DType.type is type(value) or DType.known_scalartype(type(value)):
+ return dtype.__dtype_setitem__(item_pointer, value)
+
+ # The dtype cannot handle the value, so try casting:
+ arr = np.array(value)
+ if arr.dtype is object or arr.ndim != 0:
+ # not a numpy or user scalar; try using the dtype after all:
+ return dtype.__dtype_setitem__(item_pointer, value)
+
+ arr.astype(dtype)
+ item_pointer.write(arr[()])
+
+where the call to ``np.array()`` represents the dtype discovery and is
+not actually performed.
+
+**Example:**
+
+Current ``datetime64`` returns ``np.datetime64`` scalars and can be assigned
+from ``np.datetime64``.
+However, the datetime ``__dtype_setitem__`` also allows assignment from
+date strings ("2016-05-01") or Python integers.
+Additionally the datetime ``__dtype_get_pyitem__`` function actually returns
+Python ``datetime.datetime`` object (most of the time).
+
+
+**Alternatives:**
+
+This may be seen as simply a cast to and from the ``object`` dtype.
+However, it seems slightly more complicated. This is because
+in general a Python object could itself be a zero-dimensional array or
+scalar with an associated DType.
+Thus, representing it as a normal cast would either require that:
+
+* The implementor handles all Python classes, even those for which
+ ``np.array(scalar).astype(UserDType)`` already works because
+ ``np.array(scalar)`` returns, say, a datetime64 array.
+* The cast is actually added between a typed-object to dtype. And even
+ in this case a generic fallback (for example ``float64`` can use
+ ``float(scalar)`` to do the cast) is also necessary.
+
+It is certainly possible to describe the coercion to and from Python objects
+using the general casting machinery. However, it seems special enough to
+handle specifically.
+
+
+**Further Issues and Discussion:**
+
+The setitem function currently duplicates some code, such as coercion
+from a string. ``datetime64`` allows assignment from string, but the same
+conversion also occurs for casts from the string dtype to ``datetime64``.
+In the future, we may expose a way to signal whether a conversion is known,
+and otherwise a normal cast is made so that the item is effectively set to ``np.array(scalar).astype(requested_dtype)``.
+
+There is a general issue about the handling of subclasses. We anticipate to not
+automatically detect the dtype for ``np.array(float64_subclass)`` to be
+float64. The user can still provide ``dtype=np.float64``. However, the above
+"assign by casting" using ``np.array(scalar_subclass).astype(requested_dtype)``
+will fail.
+
+.. note::
+
+ This means that ``np.complex256`` should not use ``__float__`` in its
+ ``__dtype_setitem__`` method in the future unless it is a known floating
+ point type. If the scalar is a subclass of a different high precision
+ floating point type (e.g. ``np.float128``) then this will lose precision.
+
+
+DType Discovery during Array Coercion
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An important step in the usage of NumPy arrays is the creation of the array
+itself from collections of generic Python objects.
+
+**Motivation:**
+
+Although the distinction is not clear currently, there are two main needs::
+
+ np.array([1, 2, 3, 4.])
+
+needs to guess the correct dtype based on the Python objects inside.
+Such an array may include a mix of datatypes, as long as they can be clearly
+promoted.
+Currently not clearly distinct (but partially existing for strings) is the
+use case of::
+
+ # np.dtype[np.str_] can also be spelled np.str_ or "S" (which works today)
+ np.array([object(), None], dtype=np.dtype[np.str_])
+
+which forces each object to be interpreted as string. This is anticipated
+to be useful for example for categorical datatypes::
+
+ np.array([1, 2, 1, 1, 2], dtype=Categorical)
+
+to allow the discovery the of all unique values.
+(For NumPy ``datetime64`` this is also currently used to allow string input.)
+
+There are three further issues to consider:
+
+1. It may be desirable that datatypes can be created which are associated
+ to normal Python scalars (such as ``datetime.datetime``), which do not
+ have a ``dtype`` attribute already.
+2. In general, a datatype could represent a sequence, however, NumPy currently
+ assumes that sequences are always collections of elements (the sequence cannot be an
+ element itself). An example for this is would be a ``vector`` DType.
+3. An array may itself contain arrays with a specific dtype (even
+ general Python objects). For example:
+ ``np.array([np.array(None, dtype=object)], dtype=np.String)``
+ poses the issue of how to handle the included array.
+
+Some of these difficulties arise due to the fact that finding the correct shape
+of the output array and finding the correct datatype are closely related.
+
+**Implementation:**
+
+There are two distinct cases given above: First, when the user has provided no
+dtype information, and second when the user provided a DType class –
+a notion that is currently represented e.g. by the parametric instance ``"S"``
+representing a string of any length.
+
+In the first case, it is necessary to establish a mapping from the Python type(s)
+of the constituent elements to the DType class.
+When the DType class is known, the correct dtype instance still needs to be found.
+This shall be implemented by leveraging two pieces of information:
+
+1. ``DType.type``: The current type attribute to indicate which Python scalar
+ type is associated with the DType class (this is a *class* attribute that always
+ exists for any datatype and is not limited to array coercion).
+2. The reverse lookup will remain hardcoded for the basic Python types initially.
+ Otherwise the ``type`` attribute will be used, and at least initially may
+ enforce deriving the scalar from a NumPy-provided scalar base class.
+ This method may be expanded later (see alternatives).
+3. ``__discover_descr_from_pyobject__(cls, obj) -> dtype``: A classmethod that
+ returns the correct descriptor given the input object.
+ *Note that only parametric DTypes have to implement this*, most datatypes
+ can simply use a default (singleton) dtype instance which is found only
+ based on the ``type(obj)`` of the Python object.
+
+The ``type`` which is already associated with any dtype through the
+``dtype.type`` attribute maps the DType to the Python type.
+This will be cached globally to create a mapping (dictionary)
+``known_python_types[type] = DType``.
+NumPy currently uses a small hard-coded mapping and conversion of numpy scalars
+(inheriting from ``np.generic``) to achieve this.
+
+.. note::
+
+ Python integers do not have a clear/concrete NumPy type associated with
+ them right now. This is because during array coercion NumPy currently
+ finds the first type capable of representing their value in the list
+ of `long`, `unsigned long`, `int64`, `unsigned int64`, and `object`
+ (on many machines `long` is 64 bit).
+
+ Instead they will need to be be implemented using an
+ ``AbstractPyInt``. This DType class can then provide
+ ``__discover_descr_from_pyobject__`` and return the actual dtype which
+ is e.g. ``np.dtype("int64")``.
+ For dispatching/promotion in ufuncs, it will also be necessary
+ to dynamically create ``AbstractPyInt[value]`` classes (creation can be
+ cached), so that they can provide the current functionality provided by
+ ``np.result_type(python_integer, array)``.
+
+To allow for a DType to accept specific inputs as known scalars, we will
+initially use a method such as ``known_scalar_type`` or ``known_scalar_object``
+which allows discovering an e.g. ``vector`` as a scalar (element) instead of
+a sequence (for the command ``np.array(vector, dtype=VectorDType)``).
+This will *not* be public API initially, but may be made public at a later
+time.
+
+This will work similar to the following pseudo-code::
+
+ def find_dtype(array_like):
+ common_dtype = None
+ for element in array_like:
+ # default to object dtype, if unknown
+ DType = known_python_types.get(type(element), np.dtype[object])
+ dtype = DType.__discover_descr_from_pyobject__(element)
+
+ if common_dtype is None:
+ common_dtype = dtype
+ else:
+ common_dtype = np.promote_types(common_dtype, dtype)
+
+In practice, we have to find out whether an element is actually a sequence.
+This means that instead of using the ``object`` dtype directly, we have to
+check whether or not it is a sequence.
+
+The full algorithm (without user provided dtype) thus looks more like::
+
+ def find_dtype_recursive(array_like, dtype=None):
+ """
+ Recursively find the dtype for a nested sequences (arrays are not
+ supported here).
+ """
+ DType = known_python_types.get(type(element), None)
+
+ if DType is None and is_array_like(array_like):
+ # Code for a sequence, an array_like may have a DType we
+ # can use directly:
+ for element in array_like:
+ dtype = find_dtype_recursive(element, dtype=dtype)
+ return dtype
+
+ elif DType is None:
+ DType = np.dtype[object]
+
+ # Same as above
+
+If the user provides ``DType``, then this DType will be tried first, and the
+``dtype`` may need to be cast before the promotion is performed.
+
+**Limitations:**
+
+The above issue 3. is currently (sometimes) supported by NumPy so that
+the values of an included array are inspected.
+Support in those cases may be kept for compatibility, however,
+it will not be exposed to user datatypes.
+This means that if e.g. an array with a parametric string dtype is coerced above
+(or cast) to an array of a fixed length string dtype (with unknown length),
+this will result in an error.
+Such a conversion will require passing the correct DType (fixed length of the
+string) or providing a utility function to the user.
+
+The use of a global type map means that an error or warning has to be given
+if two DTypes wish to map to the same Python type. In most cases user
+DTypes should only be implemented for types defined within the same library to
+avoid the potential for conflicts.
+It will be the DType implementor's responsibility to be careful about this and use
+the flag to disable registration when in doubt.
+
+**Alternatives:**
+
+The above proposes to add a global mapping, however, initially limiting it
+to types deriving from a NumPy subclass (and a fixed set of Python types).
+This could be relaxed in the future.
+Alternatively, we could rely on the scalar belonging to the user dtype to
+implement ``scalar.dtype`` or similar.
+
+Initially, the exact implementation shall be *undefined*, since
+scalars will have to derive from a NumPy scalar, they will also have
+a ``.dtype`` attribute. A future update can choose to use this instead
+of a global mapping.
+
+An initial alternative suggestion was to use a two-pass approach instead.
+The first pass would only find the correct DType class, and the second pass
+would then find correct dtype instance (the second pass is often not necessary).
+The advantage of this is that the DType class information is vital for universal
+functions to decide which loop to execute.
+The first pass would provide the full information necessary for value-based
+casting currently implemented for scalars, giving even the possibility of
+expanding it to e.g. list inputs ``np.add(np.array([8], dtype="uint8"), [4])``
+giving a ``uint8`` result.
+This is mainly related to the question to how the common dtype is found above.
+It seems unlikely that this is useful, and similar to a global, could be
+added later if deemed necessary.
+
+**Further Issues and Discussion:**
+
+While it is possible to create e.g. a DType such as Categorical, array,
+or vector which can only be used if `dtype=DType` is provided, if this
+is necessary these will not roundtrip correctly when converted back
+and forth::
+
+ np.array(np.array(1, dtype=Categorical)[()])
+
+requires to pass the original ``dtype=Categorical`` or returns an array
+with dtype ``object``.
+While a general limitation, the round-tripping shall always be possible if
+``dtype=old_dtype`` is provided.
+
+**Example:**
+
+The current datetime DType requires a ``__discover_descr_from_pyobject__``
+which returns the correct unit for string inputs. This allows it to support
+the current::
+
+ np.array(["2020-01-02", "2020-01-02 11:24"], dtype="M8")
+
+By inspecting the date strings. Together with the below common dtype
+operation, this allows it to automatically find that the datetime64 unit
+should be "minutes".
+
+
+Common DType Operations
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Numpy currently provides functions like ``np.result_type`` and
+``np.promote_types`` for determining common types.
+These differ in that ``np.result_type`` can take arrays and scalars as input
+and implements value based promotion [1]_.
+
+To distinguish between the promotion occurring during universal function application,
+we will call it "common type" operation here.
+
+**Motivation:**
+Common type operations are vital for array coercion when different
+input types are mixed.
+They also provide the logic currently used to decide the output dtype of
+``np.concatenate()`` and on their own are quite useful.
+
+Furthermore, common type operations may be used to find the correct dtype
+to use for functions with different inputs (including universal functions).
+This includes an interesting distinction:
+
+1. Universal functions use the DType classes for dispatching, they thus
+ require the common DType class (as a first step).
+ While this can help with finding the correct loop to execute, the loop
+ may not need the actual common dtype instance.
+ (Hypothetical example:
+ ``float_arr + string_arr -> string``, but the output string length is
+ not the same as ``np.concatenate(float_arr, string_arr)).dtype``.)
+2. Array coercion and concatenation require the common dtype *instance*.
+
+**Implementation:**
+The implementation of the common dtype (instance) determination
+has some overlap with casting.
+Casting from a specific dtype (Float64) to a String needs to find
+the correct string length (a step that is mainly necessary for parametric dtypes).
+
+We propose the following implementation:
+
+1. ``__common_dtype__(cls, other : DTypeMeta) -> DTypeMeta`` answers what the common
+ DType class is given two DType class objects.
+ It may return ``NotImplemented`` to defer to ``other``.
+ (For abstract DTypes, subclasses get precedence, concrete types are always
+ leaves, so always get preference or are tried from left to right).
+2. ``__common_instance__(self: SelfT, other : SelfT) -> SelfT`` is used when
+ two instances of the same DType are given.
+ For builtin dtypes (that are not parametric), this
+ currently always returns ``self`` (but ensures native byte order).
+ This is to preserve metadata. We can thus provide a default implementation
+ for non-parametric user dtypes.
+
+These two cases do *not* cover the case where two different dtype instances
+need to be promoted. For example `">float64"` and `"S8"`.
+The solution is partially "outsourced" to the casting machinery by
+splitting the operation up into three steps:
+
+1. ``Float64.__common_dtype__(type(>float64), type(S8))``
+ returns `String` (or defers to ``String.__common_dtype__``).
+2. The casting machinery provides the information that `">float64"` casts
+ to `"S32"` (see below for how casting will be defined).
+3. ``String.__common_instance__("S8", "S32")`` returns the final `"S32"`.
+
+The main reason for this is to avoid the need to implement
+identical functionality multiple times.
+The design (together with casting) naturally separates the concerns of
+different Datatypes.
+In the above example, Float64 does not need to know about the cast.
+While the casting machinery (``CastingImpl[Float64, String]``)
+could include the third step, it is not required to do so and the string
+can always be extended (e.g. with new encodings) without extending the
+``CastingImpl[Float64, String]``.
+
+This means the implementation will work like this::
+
+ def common_dtype(DType1, DType2):
+ common_dtype = type(dtype1).__common_dtype__(type(dtype2))
+ if common_dtype is NotImplemented:
+ common_dtype = type(dtype2).__common_dtype__(type(dtype1))
+ if common_dtype is NotImplemented:
+ raise TypeError("no common dtype")
+ return common_dtype
+
+ def promote_types(dtype1, dtyp2):
+ common = common_dtype(type(dtype1), type(dtype2))
+
+ if type(dtype1) is not common:
+ # Find what dtype1 is cast to when cast to the common DType
+ # by using the CastingImpl as described below:
+ castingimpl = get_castingimpl(type(dtype1), common)
+ safety, (_, dtype1) = castingimpl.adjust_descriptors((dtype1, None))
+ assert safety == "safe" # promotion should normally be a safe cast
+
+ if type(dtype2) is not common:
+ # Same as above branch for dtype1.
+
+ if dtype1 is not dtype2:
+ return common.__common_instance__(dtype1, dtype2)
+
+Some of these steps may be optimized for non-parametric DTypes.
+
+**Note:**
+
+A currently implemented fallback for the ``__common_dtype__`` operation
+is to use the "safe" casting logic.
+Since ``int16`` can safely cast to ``int64``, it is clear that
+``np.promote_types(int16, int64)`` should be ``int64``.
+
+However, this cannot define all such operations, and will fail for example for::
+
+ np.promote_types("int64", "float32") -> np.dtype("float64")
+
+In this design, it is the responsibility of the DType author to ensure that
+in most cases a safe-cast implies that this will be the result of the
+``__common_dtype__`` method.
+
+Note that some exceptions may apply. For example casting ``int32`` to
+a (long enough) string is – at least at this time – considered "safe".
+However ``np.promote_types(int32, String)`` will *not* be defined.
+
+**Alternatives:**
+
+The use of casting for common dtype (instance) determination neatly separates
+the concerns and allows for a minimal set of duplicate functionality
+being implemented.
+In cases of mixed DType (classes), it also adds an additional step
+to finding the common dtype.
+The common dtype (of two instances) could thus be implemented explicitly to avoid
+this indirection, potentially only as a fast-path.
+The above suggestion assumes that this is, however, not a speed relevant path,
+since in most cases, e.g. in array coercion, only a single Python type (and thus
+dtype) is involved.
+The proposed design hinges in the implementation of casting to be
+separated into its own ufunc-like object as described below.
+
+In principle common DType could be defined only based on "safe casting" rules,
+if we order all DTypes and find the first one both can cast to safely.
+However, the issue with this approach is that a newly added DType can change
+the behaviour of an existing program. For example, a new ``int24`` would be
+the first valid common type for ``int16`` and ``uint16``, demoting the currently
+defined behaviour of ``int32``.
+This API extension could be allowed in the future, while adding it may be
+more involved, the current proposal for defining casts is fully opaque in
+this regard and thus extensible.
+
+**Example:**
+
+``object`` always chooses ``object`` as the common DType. For ``datetime64``
+type promotion is defined with no other datatype, but if someone were to
+implement a new higher precision datetime, then::
+
+ HighPrecisionDatetime.__common_dtype__(np.dtype[np.datetime64])
+
+would return ``HighPrecisionDatetime``, and the below casting may need to
+decide how to handle the datetime unit.
+
+
+Casting
+^^^^^^^
+
+Maybe the most complex and interesting operation which is provided
+by DTypes is the ability to cast from one dtype to another.
+The casting operation is much like a typical function (universal function) on
+arrays converting one input to a new output.
+There are mainly two distinctions:
+
+1. Casting always requires an explicit output datatype to be given.
+2. The NumPy iterator API requires access to lower-level functions than
+ is currently necessary for universal functions.
+
+Casting from one dtype to another can be complex, and generally a casting
+function may not implement all details of each input datatype (such as
+non-native byte order or unaligned access).
+Thus casting naturally is performed in up to three steps:
+
+1. The input datatype is normalized and prepared for the actual cast.
+2. The cast is performed.
+3. The cast result, which is in a normalized form, is cast to the requested
+ form (non-native byte order).
+
+although often only step 2. is required.
+
+Further, NumPy provides different casting kinds or safety specifiers:
+
+* "safe"
+* "same_kind"
+* "unsafe"
+
+and in some cases a cast may even be represented as a simple view.
+
+
+**Motivation:**
+
+Similar to the common dtype/DType operation above, we again have two use cases:
+
+1. ``arr.astype(np.String)`` (current spelling ``arr.astype("S")``)
+2. ``arr.astype(np.dtype("S8"))``.
+
+Where the first case is also noted in NEP 40 and 41 as a design goal, since
+``np.String`` could also be an abstract DType as mentioned above.
+
+The implementation of casting should also come with as little duplicate
+implementation as necessary, i.e. to avoid unnecessary methods on the
+DTypes.
+Furthermore, it is desirable that casting is implemented similar to universal
+functions.
+
+Analogous to the above, the following also need to be defined:
+
+1. ``np.can_cast(dtype, DType, "safe")`` (instance to class)
+2. ``np.can_cast(dtype, other_dtype, "safe")`` (casting an instance to another instance)
+
+overloading the meaning of ``dtype`` to mean either class or instance
+(on the Python level).
+The question of ``np.can_cast(DType, OtherDType, "safe")`` is also a
+possibility and may be used internally.
+However, it is initially not necessary to expose to Python.
+
+
+**Implementation:**
+
+During DType creation, DTypes will have the ability to pass a list of
+``CastingImpl`` objects, which can define casting to and from the DType.
+One of these ``CastingImpl`` objects is special because it should define
+the cast within the same DType (from one instance to another).
+A DType which does not define this, must have only a single implementation
+and not be parametric.
+
+Each ``CastingImpl`` has a specific DType signature:
+``CastingImpl[InputDtype, RequestedDtype]``.
+And implements the following methods and attributes:
+
+* ``adjust_descriptors(self, Tuple[DType] : input) -> casting, Tuple[DType]``.
+ Here ``casting`` signals the casting safeness (safe, unsafe, or same-kind)
+ and the output dtype tuple is used for more multi-step casting (see below).
+* ``get_transferfunction(...) -> function handling cast`` (signature to be decided).
+ This function returns a low-level implementation of a strided casting function
+ ("transfer function").
+* ``cast_kind`` attribute with one of safe, unsafe, or same-kind. Used to
+ quickly decide casting safety when this is relevant.
+
+``adjust_descriptors`` provides information about whether or
+not a cast is safe and is of importance mainly for parametric DTypes.
+``get_transferfunction`` provides NumPy with a function capable of performing
+the actual cast. Initially the implementation of ``get_transferfunction``
+will be *private*, and users will only be able to provide contiguous loops
+with the signature.
+
+**Performing the Cast:**
+
+.. _cast_figure:
+.. figure:: _static/casting_flow.svg
+ :figclass: align-center
+
+`The above figure <cast_figure>`_ illustrates the multi-step logic necessary to
+cast for example an ``int24`` with a value of ``42`` to a string of length 20
+(``"S20"``).
+In this example, the implementer only provided the functionality of casting
+an ``int24`` to an ``S8`` string (which can hold all 24bit integers).
+Due to this limited implementation, the full cast has to do multiple
+conversions. The full process is:
+
+1. Call ``CastingImpl[Int24, String].adjust_descriptors((int24, "S20"))``.
+ This provides the information that ``CastingImpl[Int24, String]`` only
+ implements the cast of ``int24`` to ``"S8``.
+2. Since ``"S8"`` does not match ``"S20"``, use
+ ``CastingImpl[String, String].get_transferfunction()``
+ to find the transfer (casting) function to convert an ``"S8"`` into an ``"S20"``
+3. Fetch the transfer function to convert an ``int24`` to an ``"S8"`` using
+ ``CastingImpl[Int24, String].get_transferfunction()``
+4. Perform the actual cast using the two transfer functions:
+ ``int24(42) -> S8("42") -> S20("42")``.
+
+Note that in this example the ``adjust_descriptors`` function plays a less
+central role. It becomes more important for ``np.can_cast``.
+
+Further, ``adjust_descriptors`` allows the implementation for
+``np.array(42, dtype=int24).astype(String)`` to call
+``CastingImpl[Int24, String].adjust_descriptors((int24, None))``.
+In this case the result of ``(int24, "S8")`` defines the correct cast:
+``np.array(42, dtype=int24),astype(String) == np.array("42", dtype="S8")``.
+
+**Casting Safety:**
+
+To answer the question of casting safety
+``np.can_cast(int24, "S20", casting="safe")``, only the ``adjust_descriptors``
+function is required and called is in the same way as in
+`the figure describing a cast <cast_figure>`_.
+In this case, the calls to ``adjust_descriptors``, will also provide the
+information that ``int24 -> "S8"`` as well as ``"S8" -> "S20"`` are safe casts,
+and thus also the ``int24 -> "S20"`` is a safe cast.
+
+The casting safety can currently be "equivalent" when a cast is both safe
+and can be performed using only a view.
+The information that a cast is a simple "view" will instead be handled by
+an additional flag. Thus the ``casting`` can have the 6 values in total:
+safe, unsafe, same-kind as well as safe+view, unsafe+view, same-kind+view.
+Where the current "equivalent" is the same as safe+view.
+
+(For more information on the ``adjust_descriptor`` signature see the
+C-API section below.)
+
+
+**Casting between instances of the same DType:**
+
+In general one of the casting implementations define by the DType implementor
+must be ``CastingImpl[DType, DType]`` (unless there is only a singleton
+instance).
+To keep the casting to as few steps as possible, this implementation must
+be capable any conversions between all instances of this DType.
+
+
+**General Multi-Step Casting**
+
+In general we could implement certain casts, such as ``int8`` to ``int24``
+even if the user only provides an ``int16 -> int24`` cast.
+This proposal currently does not provide this functionality. However,
+it could be extended in the future to either find such casts dynamically,
+or at least allow ``adjust_descriptors`` to return arbitray ``dtypes``.
+If ``CastingImpl[Int8, Int24].adjust_descriptors((int8, int24))`` returns
+``(int16, int24)``, the actual casting process could be extended to include
+the ``int8 -> int16`` cast. Unlike the above example, which is limited
+to at most three steps.
+
+
+**Alternatives:**
+
+The choice of using only the DType classes in the first step of finding the
+correct ``CastingImpl`` means that the default implementation of
+``__common_dtype__`` has a reasonable definition of "safe casting" between
+DTypes classes (although e.g. the concatenate operation using it may still
+fail when attempting to find the actual common instance or cast).
+
+The split into multiple steps may seem to add complexity
+rather than reduce it, however, it consolidates that we have the two distinct
+signatures of ``np.can_cast(dtype, DTypeClass)`` and ``np.can_cast(dtype, other_dtype)``.
+Further, the above API guarantees the separation of concerns for user DTypes.
+The user ``Int24`` dtype does not have to handle all string lengths if it
+does not wish to do so. Further, if an encoding was added to the ``String``
+DType, this does not affect the overall cast.
+The ``adjust_descriptor`` function can keep returning the default encoding
+and the ``CastingImpl[String, String]`` can take care of any necessary encoding
+changes.
+
+The main alternative to the proposed design is to move most of the information
+which is here pushed into the ``CastingImpl`` directly into methods
+on the DTypes. This, however, will not allow the close similarity between casting
+and universal functions. On the up side, it reduces the necessary indirection
+as noted below.
+
+An initial proposal defined two methods ``__can_cast_to__(self, other)``
+to dynamically return ``CastingImpl``.
+The advantage of this addition is that it removes the requirement to know all
+possible casts at DType creation time (of one of the involved DTypes).
+Such API could be added at a later time. It should be noted, however,
+that it would be mainly useful for inheritance-like logic, which can be
+problematic. As an example two different ``Float64WithUnit`` implementations
+both could infer that they can unsafely cast between one another when in fact
+some combinations should cast safely or preserve the Unit (both of which the
+"base" ``Float64`` would discard).
+In the proposed implementation this is not possible, since the two implementations
+are not aware of each other.
+
+
+**Notes:**
+
+The proposed ``CastingImpl`` is designed to be compatible with the
+``UFuncImpl`` proposed in NEP 43.
+While initially it will be a distinct object or C-struct, the aim is that
+``CastingImpl`` can be a subclass or extension of ``UFuncImpl``.
+Once this happens, this may naturally allow the use of a ``CastingImpl`` to
+pass around a specialized casting function directly.
+
+In the future, we may consider adding a way to spell out that specific
+casts are known to be *not* possible.
+
+In the above text ``CastingImpl`` is described as a Python object. In practice,
+the current plan is to implement it as a C-side structure stored on the ``from``
+datatype.
+A Python side API to get an equivalent ``CastingImpl`` object will be created,
+but storing it (similar to the current implementation) on the ``from`` datatype
+avoids the creation of cyclic reference counts.
+
+The way dispatching works for ``CastingImpl`` is planned to be limited initially
+and fully opaque.
+In the future, it may or may not be moved into a special UFunc, or behave
+more like a universal function.
+
+
+**Example:**
+
+The implementation for casting integers to datetime would currently generally
+say that this cast is unsafe (it is always an unsafe cast).
+Its ``adjust_descriptors`` functions may look like::
+
+ def adjust_descriptors(input):
+ from_dtype, to_dtype = input
+
+ from_dtype = from_dtype.ensure_canonical() # ensure not byte-swapped
+ if to_dtype is None:
+ raise TypeError("Cannot convert to a NumPy datetime without a unit")
+ to_dtype = to_dtype.ensure_canonical() # ensure not byte-swapped
+
+ # This is always an "unsafe" cast, but for int64, we can represent
+ # it by a simple view (if the dtypes are both canonical).
+ # (represented as C-side flags here).
+ safety_and_view = NPY_UNSAFE_CASTING | NPY_CAST_IS_VIEW
+ return safety_and_view, (from_dtype, to_dtype)
+
+.. note::
+
+ While NumPy currently defines some of these casts, with the possible
+ exception of the unit-less ``timedelta64`` it may be better to not
+ define these cast at all. In general we expect that user defined
+ DTypes will be using other methods such as ``unit.drop_unit(arr)``
+ or ``arr * unit.seconds``.
+
+
+C-Side API
+^^^^^^^^^^
+
+A Python side API shall not be defined here. This is a general side approach.
+
+
+DType creation
+""""""""""""""
+
+As already mentioned in NEP 41, the interface to define new DTypes in C
+is modeled after the limited API in Python: the above-mentioned slots
+and some additional necessary information will thus be passed within a slots
+struct and identified by ``ssize_t`` integers::
+
+ static struct PyArrayMethodDef slots[] = {
+ {NPY_dt_method, method_implementation},
+ ...,
+ {0, NULL}
+ }
+
+ typedef struct{
+ PyTypeObject *typeobj; /* type of python scalar */
+ int is_parametric; /* Is the dtype parametric? */
+ int is_abstract; /* Is the dtype abstract? */
+ int flags /* flags (to be discussed) */
+ /* NULL terminated CastingImpl; is copied and references are stolen */
+ CastingImpl *castingimpls[];
+ PyType_Slot *slots;
+ PyTypeObject *baseclass; /* Baseclass or NULL */
+ } PyArrayDTypeMeta_Spec;
+
+ PyObject* PyArray_InitDTypeMetaFromSpec(PyArrayDTypeMeta_Spec *dtype_spec);
+
+all of this information will be copied during instantiation.
+
+**TODO:** The DType author should be able to at define new methods for
+their DType, up to defining a full type object and in the future possibly even
+extending the ``PyArrayDTypeMeta_Type`` struct.
+We have to decide on how (and what) to make available to the user initially.
+A proposed initial solution may be to simply allow inheriting from an existing
+class.
+Further this prevents overriding some slots, such as `==` which may not be
+desirable.
+
+
+The proposed method slots are (prepended with ``NPY_dt_``), these are
+detailed above and given here for summary:
+
+* ``is_canonical(self) -> {0, 1}``
+* ``ensure_canonical(self) -> dtype``
+* ``default_descr(self) -> dtype`` (return must be native and should normally be a singleton)
+* ``setitem(self, char *item_ptr, PyObject *value) -> {-1, 0}``
+* ``getitem(self, char *item_ptr, PyObject (base_obj) -> object or NULL``
+* ``discover_descr_from_pyobject(cls, PyObject) -> dtype or NULL``
+* ``common_dtype(cls, other) -> DType, NotImplemented, or NULL``
+* ``common_instance(self, other) -> dtype or NULL``
+
+If not set, most slots are filled with slots which either error or defer automatically.
+Non-parametric dtypes do not have to implement:
+
+* ``discover_descr_from_pyobject`` (uses ``default_descr`` instead)
+* ``common_instance`` (uses ``default_descr`` instead)
+* ``ensure_canonical`` (uses ``default_descr`` instead)
+
+Which will be correct for most dtypes *which do not store metadata*.
+
+Other slots may be replaced by convenience versions, e.g. sorting methods
+can be defined by providing:
+
+* ``compare(self, char *item_ptr1, char *item_ptr2, int *res) -> {-1, 0}``
+ *TODO: We would like an error return, is this reasonable? (similar to old
+ python compare)*
+
+which uses generic sorting functionality. In general, we could add a
+functions such as:
+
+* ``get_sort_function(self, NPY_SORTKIND sort_kind) -> {out_sortfunction, NotImplemented, NULL}``.
+ If the sortkind is not understood it may be allowed to return ``NotImplemented``.
+
+in the future. However, for example sorting is likely better solved by the
+implementation of multiple generalized ufuncs which are called internally.
+
+**Limitations:**
+
+Using the above ``PyArrayDTypeMeta_Spec`` struct, the structure itself can
+only be extended clumsily (e.g. by adding a version tag to the ``slots``
+to indicate a new, longer version of the struct).
+We could also provide the struct using a function, which however will require
+memory management but would allow ABI-compatible extension
+(the struct is freed again when the DType is created).
+
+
+CastingImpl
+"""""""""""
+
+The external API for ``CastingImpl`` will be limited initially to defining:
+
+* ``cast_kind`` attribute, which can be one of the supported casting kinds.
+ This is the safest cast possible. For example casting between two NumPy
+ strings is of course "safe" in general, but may be "same kind" in a specific
+ instance if the second string is shorter. If neither type is parametric the
+ ``adjust_descriptors`` must use it.
+* ``adjust_descriptors(dtypes_in[2], dtypes_out[2], casting_out) -> int {0, -1}``
+ The out dtypes must be set correctly to dtypes which the strided loop
+ (transfer function) can handle. Initially the result must have be instances
+ of the same DType class as the ``CastingImpl`` is defined for.
+ The ``casting_out`` will be set to ``NPY_SAFE_CASTING``, ``NPY_UNSAFE_CASTING``,
+ or ``NPY_SAME_KIND_CASTING``. With a new, additional, flag ``NPY_CAST_IS_VIEW``
+ which can be set to indicate that no cast is necessary, but a simple view
+ is sufficient to perform the cast.
+ The cast should return ``-1`` when a custom error message is set and
+ ``NPY_NO_CASTING`` to indicate that a generic casting error should be
+ set (this is in most cases preferable).
+* ``strided_loop(char **args, npy_intp *dimensions, npy_intp *strides, dtypes[2]) -> int {0, nonzero}`` (must currently succeed)
+
+This is identical to the proposed API for ufuncs. By default the two dtypes
+are passed in as the last argument. On error return (if no error is set) a
+generic error will be given.
+More optimized loops are in use internally, and will be made available to users
+in the future (see notes)
+The iterator API does not currently support casting errors: this is
+a bug that needs to be fixed. Until it is fixed the loop should always
+succeed (return 0).
+
+Although verbose, the API shall mimic the one for creating a new DType.
+The ``PyArrayCastingImpl_Spec`` will include a field for ``dtypes`` and
+identical to a ``PyArrayUFuncImpl_Spec``::
+
+ typedef struct{
+ int needs_api; /* whether the cast requires the API */
+ PyArray_DTypeMeta *in_dtype; /* input DType class */
+ PyArray_DTypeMeta *out_dtype; /* output DType class */
+ /* NULL terminated slots defining the methods */
+ PyType_Slot *slots;
+ } PyArrayUFuncImpl_Spec;
+
+The actual creation function ``PyArrayCastingImpl_FromSpec()`` will additionally
+require a ``casting`` parameter to define the default (maximum) casting safety.
+The internal representation of ufuncs and casting implementations may differ
+initially if it makes implementation simpler, but should be kept opaque to
+allow future merging.
+
+**TODO:** It may be possible to make this more close to the ufuncs or even
+use a single FromSpec. This API shall only be finalized after/when NEP 43
+is finalized.
+
+**Notes:**
+
+We may initially allow users to define only a single loop.
+However, internally NumPy optimizes far more, and this should be made
+public incrementally, by either allowing to provide multiple versions, such
+as:
+
+* contiguous inner loop
+* strided inner loop
+* scalar inner loop
+
+or more likely through an additional ``get_inner_loop`` function which has
+additional information, such as the fixed strides (similar to our internal API).
+
+The above example does not yet include the definition of setup/teardown
+functionality, which may overlap with ``get_inner_loop``.
+Since these are similar to the UFunc machinery, this should be defined in
+detail in NEP 43 and then incorporated identically into casting.
+
+Also the ``needs_api`` decision may actually be moved into a setup function,
+and removed or mainly provided as a convenience flag.
+
+The slots/methods used will be prefixed ``NPY_uf_`` for similarity to the ufunc
+machinery.
+
+
+
+Alternatives
+""""""""""""
+
+Aside from name changes, and possible signature tweaks, there seem to
+be few alternatives to the above structure.
+Keeping the creation process close the Python limited API has some advantage.
+Convenience functions could still be provided to allow creation with less
+code.
+The central point in the above design is that the enumerated slots design
+is extensible and can be changed without breaking binary compatibility.
+A downside is the possible need to pass in e.g. integer flags using a void
+pointer inside this structure.
+
+A downside of this is that compilers cannot warn about function
+pointer incompatibilities. There is currently no proposed solution to this.
+
+
+Issues
+^^^^^^
+
+Any possible design decision will have issues.
+
+The above split into Python objects has the disadvantage that reference cycles
+naturally occur. For example a potential ``CastingImpl`` object needs to
+hold on to both ``DTypes``. Further, a scalar type may want to own a
+strong reference to the corresponding ``DType`` while the ``DType`` *must*
+hold a strong reference to the scalar.
+We do not believe that these reference cycles are an issue. The may
+require implementation of of cyclic reference counting at some point, but
+cyclic reference resolution is very common in Python and dtypes (especially
+classes) are only a small number of objects.
+
+In some cases, the new split will add additional indirections to the code,
+since methods on the DType have to be looked up and called.
+This should not have serious performance impact and seems necessary to
+achieve the desired flexibility.
+
+From a user-perspective, a more serious downside is that handling certain
+functionality in the ``DType`` rather than directly can mean that error
+messages need to be raised from places where less context is available.
+This may mean that error messages can be less specific.
+This will be alleviated by exception chaining. Also decisions such as
+returning the casting safety (even when it is impossible to cast) allow
+most exceptions to be set at a point where more context is available
+and ensures uniform errors messages.
+
+
+Implementation
+--------------
+
+Internally a few implementation details have to be decided. These will be
+fully opaque to the user and can be changed at a later time.
+
+This includes:
+
+* How ``CastingImpl`` lookup, and thus the decision whether a cast is possible,
+ is defined. (This is speed relevant, although mainly during a transition
+ phase where UFuncs where NEP 43 is not yet implemented).
+ Thus, it is not very relevant to the NEP. It is only necessary to ensure fast
+ lookup during the transition phase for the current builtin Numerical types.
+
+* How the mapping from a python scalar (e.g. ``3.``) to the DType is
+ implemented.
+
+The main steps for implementation are outlined in :ref:`NEP 41 <NEP41>`.
+This includes the internal restructure for how casting and array-coercion
+works.
+After this the new public API will be added incrementally.
+This includes replacements for certain slots which are occasionally
+directly used on the dtype (e.g. ``dtype->f->setitem``).
+
+
+Discussion
+----------
+
+There is a large space of possible implementations with many discussions
+in various places, as well as initial thoughts and design documents.
+These are listed in the discussion of NEP 40 and not repeated here for
+brevity.
+
+
+References
+----------
+
+.. [1] NumPy currently inspects the value to allow the operations::
+
+ np.array([1], dtype=np.uint8) + 1
+ np.array([1.2], dtype=np.float32) + 1.
+
+ to return a ``uint8`` or ``float32`` array respectively. This is
+ further described in the documentation of `numpy.result_type`.
+
+
+Copyright
+---------
+
+This document has been placed in the public domain.
diff --git a/doc/neps/nep-0045-c_style_guide.rst b/doc/neps/nep-0045-c_style_guide.rst
index 3c21e404f..f579e4f69 100644
--- a/doc/neps/nep-0045-c_style_guide.rst
+++ b/doc/neps/nep-0045-c_style_guide.rst
@@ -1,3 +1,5 @@
+.. _NEP45:
+
=================================
NEP 45 — C Style Guide
=================================
@@ -71,8 +73,8 @@ C dialect
* No compiler warnings with major compilers (gcc, VC++, a few others).
-.. Note::
- NumPy still produces compiler warnings that need to be addressed.
+.. note::
+ NumPy still produces compiler warnings that need to be addressed.
Code layout
============
@@ -226,7 +228,8 @@ Naming conventions
``array_real_get``. Single leading underscores should not be used, but
some current function names violate that rule due to historical accident.
-.. Note::
+.. note::
+
Functions whose names begin with a single underscore should be renamed at
some point.
@@ -244,7 +247,7 @@ C functions, see the files in ``doc/cdoc/``.
Related Work
------------
-Based on Van Rossum and Warsaw, `PEP 7 -- Style Guide for C Code <https://www.python.org/dev/peps/pep-0007>`_
+Based on Van Rossum and Warsaw, :pep:`7`
Discussion
diff --git a/doc/neps/roadmap.rst b/doc/neps/roadmap.rst
index 3780499a0..40fcbd325 100644
--- a/doc/neps/roadmap.rst
+++ b/doc/neps/roadmap.rst
@@ -6,6 +6,7 @@ This is a live snapshot of tasks and features we will be investing resources
in. It may be used to encourage and inspire developers and to search for
funding.
+
Interoperability
----------------
@@ -16,11 +17,21 @@ facilitate interoperability with all such packages, and the code that uses them,
may include (among other things) interoperability protocols, better duck typing
support and ndarray subclass handling.
-- The ``__array_function__`` protocol is currently experimental and needs to be
- matured. See :ref`NEP18` for details.
-- New protocols for overriding other functionality in NumPy may be needed.
-- Array duck typing, or handling "duck arrays", needs improvements. See
- :ref:`NEP22` for details.
+The ``__array_ufunc__`` and ``__array_function__`` protocols are stable, but
+do not cover the whole API. New protocols for overriding other functionality
+in NumPy are needed. Work in this area aims to bring to completion one or more
+of the following proposals:
+
+- :ref:`NEP30`
+- :ref:`NEP31`
+- :ref:`NEP35`
+- :ref:`NEP37`
+
+In addition we aim to provide ways to make it easier for other libraries to
+implement a NumPy-compatible API. This may include defining consistent subsets
+of the API, as discussed in `this section of NEP 37
+<https://numpy.org/neps/nep-0037-array-module.html#requesting-restricted-subsets-of-numpy-s-api>`__.
+
Extensibility
-------------
@@ -42,56 +53,59 @@ improve the dtype system.
- One of these should probably be the default for text data. The current
behavior on Python 3 is neither efficient nor user friendly.
-- ``np.dtype(int)`` should not be platform dependent
-- Better coercion for string + number
Performance
-----------
-We want to further improve NumPy's performance, through:
+Improvements to NumPy's performance are important to many users. The primary
+topic at the moment is better use of SIMD instructions, also on platforms other
+than x86 - see :ref:`NEP38`.
+
+Other performance improvement ideas include:
-- Better use of SIMD instructions, also on platforms other than x86.
-- Reducing ufunc overhead.
+- Reducing ufunc and ``__array_function__`` overhead.
- Optimizations in individual functions.
+- A better story around parallel execution.
Furthermore we would like to improve the benchmarking system, in terms of coverage,
easy of use, and publication of the results (now
`here <https://pv.github.io/numpy-bench>`__) as part of the docs or website.
+
Website and documentation
-------------------------
-Our website (https://numpy.org) is in very poor shape and needs to be rewritten
-completely.
-
-The NumPy `documentation <https://www.numpy.org/devdocs/user/index.html>`__ is
-of varying quality - in particular the User Guide needs major improvements.
+The NumPy `documentation <https://www.numpy.org/devdocs>`__ is of varying
+quality. The API documentation is in good shape; tutorials and high-level
+documentation on many topics are missing or outdated. See :ref:`NEP44` for
+planned improvements.
-Random number generation policy & rewrite
------------------------------------------
+Our website (https://numpy.org) was completely redesigned recently. We aim to
+further improve it by adding translations, better Hugo-Sphinx integration via a
+new Sphinx theme, and more (see `this tracking issue <https://github.com/numpy/numpy.org/issues/266>`__).
-A new random number generation framework with higher performance generators is
-close to completion, see :ref:`NEP19` and `PR 13163`_.
-Indexing
---------
+User experience
+---------------
-We intend to add new indexing modes for "vectorized indexing" and "outer indexing",
-see :ref:`NEP21`.
+Type annotations
+````````````````
+We aim to add type annotations for all NumPy functionality, so users can use
+tools like `mypy`_ to type check their code and IDEs can improve their support
+for NumPy. The existing type stubs in the `numpy-stubs`_ repository are being
+improved and will be moved into the NumPy code base.
-Continuous Integration
-----------------------
+Platform support
+````````````````
+We aim to increase our support for different hardware architectures. This
+includes adding CI coverage when CI services are available, providing wheels on
+PyPI for ARM64 (``aarch64``) and POWER8/9 (``ppc64le``), providing better
+build and install documentation, and resolving build issues on other platforms
+like AIX.
-We depend on CI to discover problems as we continue to develop NumPy before the
-code reaches downstream users.
-- CI for more exotic platforms (if available as a service).
-- Multi-package testing
-- Add an official channel for numpy dev builds for CI usage by other projects so
- they may confirm new builds do not break their package.
-
-Other functionality
--------------------
+Maintenance
+-----------
- ``MaskedArray`` needs to be improved, ideas include:
@@ -99,12 +113,17 @@ Other functionality
- MaskedArray as a duck-array type, and/or
- dtypes that support missing values
-- A backend system for ``numpy.fft`` (so that e.g. ``fft-mkl`` doesn't need to monkeypatch numpy)
-- Write a strategy on how to deal with overlap between NumPy and SciPy for ``linalg``
- and ``fft`` (and implement it).
-- Deprecate ``np.matrix`` (very slowly)
+- Fortran integration via ``numpy.f2py`` requires a number of improvements, see
+ `this tracking issue <https://github.com/numpy/numpy/issues/14938>`__.
+- A backend system for ``numpy.fft`` (so that e.g. ``fft-mkl`` doesn't need to monkeypatch numpy).
+- Write a strategy on how to deal with overlap between NumPy and SciPy for ``linalg``.
+- Deprecate ``np.matrix`` (very slowly).
+- Add new indexing modes for "vectorized indexing" and "outer indexing" (see :ref:`NEP21`).
+- Make the polynomial API easier to use.
+- Integrate an improved text file loader.
+- Ufunc and gufunc improvements, see `gh-8892 <https://github.com/numpy/numpy/issues/8892>`__
+ and `gh-11492 <https://github.com/numpy/numpy/issues/11492>`__.
-.. _implementation: https://gist.github.com/shoyer/1f0a308a06cd96df20879a1ddb8f0006
-.. _`reference implementation`: https://github.com/bashtage/randomgen
-.. _`PR 13163`: https://github.com/numpy/numpy/pull/13163
+.. _`mypy`: https://mypy.readthedocs.io
+.. _`numpy-stubs`: https://github.com/numpy/numpy-stubs
diff --git a/doc/release/upcoming_changes/16056.deprecation.rst b/doc/release/upcoming_changes/16056.deprecation.rst
new file mode 100644
index 000000000..788b8c30a
--- /dev/null
+++ b/doc/release/upcoming_changes/16056.deprecation.rst
@@ -0,0 +1,13 @@
+Inexact matches for mode and searchside are deprecated
+------------------------------------------------------
+Inexact and case insensitive matches for mode and searchside were
+valid inputs earlier and will give a DeprecationWarning now.
+For example, below are some example usages which are now deprecated and will
+give a DeprecationWarning.
+
+ import numpy as np
+ arr = np.array([[3, 6, 6], [4, 5, 1]])
+ # mode: inexact match
+ np.ravel_multi_index(arr, (7, 6), mode="clap") # should be "clip"
+ # searchside: inexact match
+ np.searchsorted(arr[0], 4, side='random') # should be "right"
diff --git a/doc/release/upcoming_changes/16515.new_feature.rst b/doc/release/upcoming_changes/16515.new_feature.rst
new file mode 100644
index 000000000..5b3803429
--- /dev/null
+++ b/doc/release/upcoming_changes/16515.new_feature.rst
@@ -0,0 +1,8 @@
+NumPy is now typed
+------------------
+Type annotations have been added for large parts of NumPy. There is
+also a new `numpy.typing` module that contains useful types for
+end-users. The currently available types are
+
+- ``ArrayLike``: for objects that can be coerced to an array
+- ``DtypeLike``: for objects that can be coerced to a dtype
diff --git a/doc/release/upcoming_changes/16519.improvement.rst b/doc/release/upcoming_changes/16519.improvement.rst
new file mode 100644
index 000000000..50c4305e5
--- /dev/null
+++ b/doc/release/upcoming_changes/16519.improvement.rst
@@ -0,0 +1,4 @@
+Thread-safe f2py callback functions
+-----------------------------------
+
+Callback functions in f2py are now threadsafe.
diff --git a/doc/release/upcoming_changes/16554.compatibility.rst b/doc/release/upcoming_changes/16554.compatibility.rst
new file mode 100644
index 000000000..a9f3f07e0
--- /dev/null
+++ b/doc/release/upcoming_changes/16554.compatibility.rst
@@ -0,0 +1,10 @@
+Numeric-style type names have been removed from type dictionaries
+-----------------------------------------------------------------
+
+To stay in sync with the deprecation for ``np.dtype("Complex64")``
+and other numeric-style (capital case) types. These were removed
+from ``np.sctypeDict`` and ``np.typeDict``. You should use
+the lower case versions instead. Note that ``"Complex64"``
+corresponds to ``"complex128"`` and ``"Complex32"`` corresponds
+to ``"complex64"``. The numpy style (new) versions, denote the full
+size and not the size of the real/imaginary part.
diff --git a/doc/release/upcoming_changes/16554.deprecation.rst b/doc/release/upcoming_changes/16554.deprecation.rst
new file mode 100644
index 000000000..5602d2d53
--- /dev/null
+++ b/doc/release/upcoming_changes/16554.deprecation.rst
@@ -0,0 +1,8 @@
+Further Numeric Style types Deprecated
+--------------------------------------
+
+The remaining numeric-style type codes ``Bytes0``, ``Str0``,
+``Uint32``, ``Uint64``, and ``Datetime64``
+have been deprecated. The lower-case variants should be used
+instead. For bytes and string ``"S"`` and ``"U"``
+are further alternatives.
diff --git a/doc/release/upcoming_changes/16554.expired.rst b/doc/release/upcoming_changes/16554.expired.rst
new file mode 100644
index 000000000..9b5718f8a
--- /dev/null
+++ b/doc/release/upcoming_changes/16554.expired.rst
@@ -0,0 +1,5 @@
+* The deprecation of numeric style type-codes ``np.dtype("Complex64")``
+ (with upper case spelling), is expired. ``"Complex64"`` corresponded to
+ ``"complex128"`` and ``"Complex32"`` corresponded to ``"complex64"``.
+* The deprecation of ``np.sctypeNA`` and ``np.typeNA`` is expired. Both
+ have been removed from the public API. Use ``np.typeDict`` instead.
diff --git a/doc/source/conf.py b/doc/source/conf.py
index d6a0f8bf3..65dcae245 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -240,11 +240,12 @@ texinfo_documents = [
# Intersphinx configuration
# -----------------------------------------------------------------------------
intersphinx_mapping = {
+ 'neps': ('https://numpy.org/neps', None),
'python': ('https://docs.python.org/dev', None),
'scipy': ('https://docs.scipy.org/doc/scipy/reference', None),
'matplotlib': ('https://matplotlib.org', None),
'imageio': ('https://imageio.readthedocs.io/en/stable', None),
- 'skimage': ('https://scikit-image.org/docs/stable', None)
+ 'skimage': ('https://scikit-image.org/docs/stable', None),
}
diff --git a/doc/source/dev/gitwash/git_links.inc b/doc/source/dev/gitwash/git_links.inc
index 82e6c75e5..8032dca41 100644
--- a/doc/source/dev/gitwash/git_links.inc
+++ b/doc/source/dev/gitwash/git_links.inc
@@ -16,7 +16,7 @@
.. _subversion: http://subversion.tigris.org/
.. _git cheat sheet: http://cheat.errtheblog.com/s/git
.. _pro git book: https://git-scm.com/book/
-.. _git svn crash course: https://git-scm.com/course/svn.html
+.. _git svn crash course: https://git.wiki.kernel.org/index.php/GitSvnCrashCourse
.. _learn.github: https://learn.github.com/
.. _network graph visualizer: https://github.blog/2008-04-10-say-hello-to-the-network-graph-visualizer/
.. _git user manual: https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
@@ -42,7 +42,7 @@
.. _why the -a flag?: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html
.. _git staging area: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html
.. _tangled working copy problem: https://tomayko.com/writings/the-thing-about-git
-.. _git management: http://kerneltrap.org/Linux/Git_Management
+.. _git management: https://web.archive.org/web/20090328043540/http://kerneltrap.org/Linux/Git_Management
.. _linux git workflow: https://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html
.. _ipython git workflow: https://mail.python.org/pipermail/ipython-dev/2010-October/005632.html
.. _git parable: http://tom.preston-werner.com/2009/05/19/the-git-parable.html
diff --git a/doc/source/dev/governance/governance.rst b/doc/source/dev/governance/governance.rst
index d8719700f..9209f26b7 100644
--- a/doc/source/dev/governance/governance.rst
+++ b/doc/source/dev/governance/governance.rst
@@ -387,8 +387,7 @@ Acknowledgements
================
Substantial portions of this document were adapted from the
-`Jupyter/IPython project's governance document
-<https://github.com/jupyter/governance/blob/master/governance.md>`_.
+`Jupyter/IPython project's governance document <https://github.com/jupyter/governance>`_
License
=======
diff --git a/doc/source/dev/howto-docs.rst b/doc/source/dev/howto-docs.rst
index 0e2e03e0b..17194bd58 100644
--- a/doc/source/dev/howto-docs.rst
+++ b/doc/source/dev/howto-docs.rst
@@ -4,146 +4,153 @@
How to contribute to the NumPy documentation
############################################
-The *Documentation* for a software project is the set of reference,
-instructional, educational, informative material generated by the project
-developers and contributors, as well as discussions, presentations, videos and
-other user-generated content. It may include learning-oriented content (such as
-tutorials and how-tos), use-cases or in-depth explanations and reference for
-developers.
-
-If you're reading this page, you probably want to help. This guide is meant to
-help you decide which kind of content you'll write, as well as give you some
-tips and instructions for submitting it to the official NumPy documentation
-(that is, the documentation that ships with NumPy and lives on the
-:ref:`official project pages <numpy_docs_mainpage>`). Keep in mind that if you
-don't want to do this, writing a tutorial on your own blog, creating a YouTube
-video or answering questions on social media or Stack Overflow are also great
-contributions!
-
-NumPy has a Documentation Team. We have open meetings on Zoom every three weeks
-and invite everyone to join. Don't hesitate to reach out if you have questions
-or just need someone to guide you through your first steps - we're always happy
-to help. Meetings are usually announced on the `numpy-discussion mailing list
-<https://mail.python.org/mailman/listinfo/numpy-discussion>`__. Meeting minutes
-are taken `on hackmd.io <https://hackmd.io/oB_boakvRqKR-_2jRV-Qjg>`__ and stored
-in the `NumPy Archive repository <https://github.com/numpy/archive>`__.
-
-You can find larger planned and in-progress documentation improvement ideas `at
+This guide will help you decide what to contribute and how to submit it to the
+official NumPy documentation.
+
+******************************************************************************
+Documentation team meetings
+******************************************************************************
+
+The NumPy community has set a firm goal of improving its documentation. We
+hold regular documentation meetings on Zoom (dates are announced on the
+`numpy-discussion mailing list
+<https://mail.python.org/mailman/listinfo/numpy-discussion>`__), and everyone
+is welcome. Reach out if you have questions or need
+someone to guide you through your first steps -- we're happy to help.
+Minutes are taken `on hackmd.io <https://hackmd.io/oB_boakvRqKR-_2jRV-Qjg>`__
+and stored in the `NumPy Archive repository
+<https://github.com/numpy/archive>`__.
+
+*************************
+What's needed
+*************************
+NumPy docs have the details covered. API reference
+documentation is generated directly from
+`docstrings <https://www.python.org/dev/peps/pep-0257/>`_ in the code
+when the documentation is :ref:`built<howto-build-docs>`.
+
+What we lack are docs with broader scope -- tutorials, how-tos, and explanations.
+Reporting defects is another way to contribute. We discuss both.
+
+*************************
+Contributing fixes
+*************************
+
+We're eager to hear about and fix doc defects. But to attack the biggest
+problems we end up having to defer or overlook some bug reports. Here are the
+best defects to go after.
+
+Top priority goes to **technical inaccuracies** -- a docstring missing a
+parameter, a faulty description of a function/parameter/method, and so on.
+Other "structural" defects like broken links also get priority. All these fixes
+are easy to confirm and put in place. You can submit
+a `pull request (PR) <https://numpy.org/devdocs/dev/index.html#devindex>`__
+with the fix, if you know how to do that; otherwise please `open an issue
+<https://github.com/numpy/numpy/issues>`__.
+
+**Typos and misspellings** fall on a lower rung; we welcome hearing about them but
+may not be able to fix them promptly. These too can be handled as pull
+requests or issues.
+
+Obvious **wording** mistakes (like leaving out a "not") fall into the typo
+category, but other rewordings -- even for grammar -- require a judgment call,
+which raises the bar. Test the waters by first presenting the fix as an issue.
+
+******************************************************************************
+Contributing new pages
+******************************************************************************
+
+Your frustrations using our documents are our best guide to what needs fixing.
+
+If you write a missing doc you join the front line of open source, but it's
+a meaningful contribution just to let us know what's missing. If you want to
+compose a doc, run your thoughts by the `mailing list
+<https://mail.python.org/mailman/listinfo/numpy-discussion>`__ for futher
+ideas and feedback. If you want to alert us to a gap,
+`open an issue <https://github.com/numpy/numpy/issues>`__. See
+`this issue <https://github.com/numpy/numpy/issues/15760>`__ for an example.
+
+If you're looking for subjects, our formal roadmap for documentation is a
+*NumPy Enhancement Proposal (NEP)*,
+`NEP 44 - Restructuring the NumPy Documentation <https://www.numpy.org/neps/nep-0044-restructuring-numpy-docs>`__.
+It identifies areas where our docs need help and lists several
+additions we'd like to see, including Jupyter notebooks.
+
+You can find larger planned and in-progress ideas `at
our GitHub project <https://github.com/orgs/numpy/projects/2>`__.
-Current vision for the documentation: NEP 44
---------------------------------------------
+.. _tutorials_howtos_explanations:
-Recently, the NumPy community approved a *NumPy Enhancement Proposal (NEP)*
-about documentation, `NEP 44 - Restructuring the NumPy Documentation
-<https://www.numpy.org/neps/nep-0044-restructuring-numpy-docs>`__.
-**Where is the documentation?**
+Formula writing
+==============================================================================
+There are formulas for writing useful documents, and four formulas
+cover nearly everything. There are four formulas because there are four
+categories of document -- ``tutorial``, ``how-to guide``, ``explanation``,
+and ``reference``. The insight that docs divide up this way belongs to
+Daniele Procida, who goes on
+`in this short article <https://documentation.divio.com/>`__ to explain
+the differences and reveal the formulas. When you begin a document or
+propose one, have in mind which of these types it will be.
-The main page for the :ref:`NumPy Documentation <numpy_docs_mainpage>` lists
-several categories. The documents mentioned there live in different places.
-- **Tutorials, How-Tos, Explanations:** These documents are stored in the NumPy
- source code tree, which means that in order to add them to the official
- documentation, you have to download the NumPy source code,
- :ref:`build it <howto-build-docs>` and submit your changes via a
- :ref:`GitHub pull request <devindex>`.
+.. _contributing:
-- **API Reference:** These are mainly the result of rendering the NumPy code
- `docstrings <https://www.python.org/dev/peps/pep-0257/>`__ into formatted
- documents. They are automatically generated when the NumPy documentation is
- :ref:`built from source<howto-build-docs>`.
-**Datasets**
+More on contributing
+==============================================================================
-If you are writing a tutorial or how-to, we encourage you to use real images and
-data (provided they are appropriately licensed and available). This makes the
-material more engaging for readers, and choosing the right data can add
-pedagogical value to your content.
+Don't worry if English is not your first language, or if you can only come up
+with a rough draft. Open source is a community effort. Do your best -- we'll
+help fix issues.
-*Note: currently we cannot easily use data in other packages (except, e.g., from
-SciPy or Matplotlib). We plan to create a dedicated datasets package, but that's
-not ready yet - please discuss with us if you have data sources in mind.*
+Images and real-life data make text more engaging and powerful, but be sure
+what you use is appropriately licensed and available. Here again, even a rough
+idea for artwork can be polished by others.
-Creating new content
---------------------
+For now, the only data formats accepted by NumPy are those also used by other
+Python scientific libraries like pandas, SciPy, or Matplotlib. We're
+developing a package to accept more formats; contact us for details.
-The documentation is written in restructuredText, which is the format required
-by Sphinx, the tool most Python projects use to automatically build and link the
-documentation within the project. You can read the
-`Quick reStructuredText Guide
+NumPy documentation is kept in the source code tree. To get your document
+into the docbase you must download the tree, :ref:`build it
+<howto-build-docs>`, and submit a pull request. If GitHub and pull requests
+are new to you, check our :ref:`Contributor Guide <devindex>`.
+
+Our markup language is reStructuredText (rST), which is more elaborate than
+Markdown. Sphinx, the tool many Python projects use to build and link project
+documentation, converts the rST into HTML and other formats. For more on
+rST, see the `Quick reStructuredText Guide
<https://docutils.sourceforge.io/docs/user/rst/quickref.html>`__ or the
`reStructuredText Primer
-<http://www.sphinx-doc.org/en/stable/usage/restructuredtext/basics.html>`__ for
-more information.
-
-If you have already decided which type of document you want to write, you can
-check out the following specific guides:
-
-- Guide to writing Tutorials (TODO)
-- :ref:`Guide to writing reference (API) documentation: the numpydoc docstring
- guide <howto-document>`
-
-Major additions to the documentation (e.g. new tutorials) should be proposed to
-the `mailing list
-<https://mail.python.org/mailman/listinfo/numpy-discussion>`__.
-
-Other ways to contribute
-------------------------
-
-Correcting technical inaccuracies in the documentation are high priority. For
-example, if a docstring is missing a parameter or the description of a
-fuction/parameter/method etc. is incorrect. Other "structural" defects like
-broken links are also high priority.
-
-Proposals for changes that improve the clarity of the documentation are welcome.
-However, "clarity" is a bit subjective, so such proposals are best made by
-raising issues that describe what could be improved in the current
-documentation. Proposals that include specific suggestions for the improvement
-are encouraged as the proposed changes helps frame the discussion.
-
-Based on the above characterization, "high-priority" changes (i.e. fixing
-technical inaccuracies, broken links, etc.) can be proposed via pull requests
-directly as they are straightforward to review. Other changes should be raised
-as issues first so that the discussion can happen before you make major
-modifications, which in principle saves you from wasting your time on
-undesired changes.
-
-If you see a good tutorial, how-to or explanation that is not included in the
-official documentation, you can suggest it to be added by `opening an issue on
-GitHub <https://github.com/numpy/numpy/issues>`__. Similarly, opening issues to
-suggest a tutorial, how-to or explanation that you can't find anywhere is a
-great way to help the documentation team direct efforts towards what users are
-looking for. `See this issue <https://github.com/numpy/numpy/issues/15760>`__
-for an example of how to do this.
-
-Finally, if you detect a typo or an error in the documentation, or would like to
-suggest a different approach, you can also open an issue or submit a pull
-request with your suggestion. Keep in mind that changes fixing
-grammatical/spelling errors are welcome but not necessarily the highest
-priority. "Grammatical correctness" often gets confused with "style" which can
-result in unfruitful discussions that don't necessarily improve anything.
-Changes that modify wording or rearrange phrasing without changing the technical
-content are discouraged. If you think that a different wording improves clarity,
-you should open an issue as noted above, but again, changes along these lines
-very often tend to be highly subjective and not necessarily do much to improve
-the quality of the documentation.
-
-**Final tips**
-
-- Don't worry if English is not your first language. Do your best - we'll revise
- your content and make sure we fix any issues with the code or text.
-- If you are unsure whether your tutorial is useful to the community, consider
- submitting an issue on GitHub suggesting it, or asking on the mailing
- list or Stack Overflow.
-- If you are unfamiliar with git/GitHub or the process of submitting a pull
- request (PR), check our :ref:`Contributor Guide <devindex>`.
-
-**Other interesting material**
-
-- `writethedocs.org <https://www.writethedocs.org/>`__ has a lot of interesting
- resources for technical writing.
-- Google offers two free `Technical Writing Courses
- <https://developers.google.com/tech-writing>`__
-- `Software Carpentry <https://software-carpentry.org/software>`__ has a lot of
- nice recommendations for creating educational material.
+<http://www.sphinx-doc.org/en/stable/usage/restructuredtext/basics.html>`__
+
+
+************************************************************
+Contributing indirectly
+************************************************************
+
+If you run across outside material that would be a useful addition to the
+NumPy docs, let us know by `opening an issue <https://github.com/numpy/numpy/issues>`__.
+
+You don't have to contribute here to contribute to NumPy. You've contributed
+if you write a tutorial on your blog, create a YouTube video, or answer questions
+on Stack Overflow and other sites.
+
+
+************************************************************
+Documentation reading
+************************************************************
+
+- The leading organization of technical writers,
+ `Write the Docs <https://www.writethedocs.org/>`__,
+ holds conferences, hosts learning resources, and runs a Slack channel.
+
+- "Every engineer is also a writer," says Google's
+ `collection of technical writing resources <https://developers.google.com/tech-writing>`__,
+ which includes free online courses for developers in planning and writing
+ documents.
+
+- `Software Carpentry's <https://software-carpentry.org/lessons>`__ mission is
+ teaching software to researchers. In addition to hosting the curriculum, the
+ website explains how to present ideas effectively.
diff --git a/doc/source/dev/index.rst b/doc/source/dev/index.rst
index 5270bfb77..aeb277a87 100644
--- a/doc/source/dev/index.rst
+++ b/doc/source/dev/index.rst
@@ -140,8 +140,7 @@ Here's the short summary, complete TOC links are below:
If your change introduces a deprecation, make sure to discuss this first on
GitHub or the mailing list first. If agreement on the deprecation is
- reached, follow `NEP 23 deprecation policy <http://www.numpy.org/neps/
- nep-0023-backwards-compatibility.html>`_ to add the deprecation.
+ reached, follow :ref:`NEP 23 deprecation policy <NEP23>` to add the deprecation.
6. Cross referencing issues
@@ -189,7 +188,7 @@ Stylistic Guidelines
import numpy as np
-* For C code, see the :ref:`numpy-c-style-guide<style_guide>`
+* For C code, see :ref:`NEP 45 <NEP45>`.
Test coverage
@@ -256,7 +255,7 @@ From the ``doc/`` directory:
git submodule update --init
The documentation includes mathematical formulae with LaTeX formatting.
-A working LaTeX document production system
+A working LaTeX document production system
(e.g. `texlive <https://www.tug.org/texlive/>`__) is required for the
proper rendering of the LaTeX math in the documentation.
@@ -291,4 +290,4 @@ The rest of the story
NumPy-specific workflow is in :ref:`numpy-development-workflow
<development-workflow>`.
-.. _`mailing list`: https://mail.python.org/mailman/listinfo/numpy-devel
+.. _`mailing list`: https://mail.python.org/mailman/listinfo/numpy-discussion
diff --git a/doc/source/reference/arrays.classes.rst b/doc/source/reference/arrays.classes.rst
index 6c8793342..c5563bddd 100644
--- a/doc/source/reference/arrays.classes.rst
+++ b/doc/source/reference/arrays.classes.rst
@@ -173,7 +173,7 @@ NumPy provides several hooks that classes can customize:
- ``func`` is an arbitrary callable exposed by NumPy's public API,
which was called in the form ``func(*args, **kwargs)``.
- - ``types`` is a `collection <collections.abc.Collection>`_
+ - ``types`` is a collection :py:class:`collections.abc.Collection`
of unique argument types from the original NumPy function call that
implement ``__array_function__``.
- The tuple ``args`` and dict ``kwargs`` are directly passed on from the
diff --git a/doc/source/reference/global_state.rst b/doc/source/reference/global_state.rst
index 2a163390e..7bf9310e8 100644
--- a/doc/source/reference/global_state.rst
+++ b/doc/source/reference/global_state.rst
@@ -81,5 +81,5 @@ This setting should always be enabled. Setting the
debug option can be interesting for testing code written
in C which iterates through arrays that may or may not be
contiguous in memory.
-Most users will have no reason to change these, for details
-please see the `memory layout <memory-layout>`_ documentation.
+Most users will have no reason to change these; for details
+see the :ref:`memory layout <memory-layout>` documentation.
diff --git a/doc/source/reference/random/new-or-different.rst b/doc/source/reference/random/new-or-different.rst
index 03e7775a0..6cab0f729 100644
--- a/doc/source/reference/random/new-or-different.rst
+++ b/doc/source/reference/random/new-or-different.rst
@@ -15,7 +15,7 @@ What's New or Different
streams, use `RandomState`, i.e., `RandomState.gamma` or
`RandomState.standard_t`.
-Quick comparison of legacy `mtrand <legacy>`_ to the new `Generator`
+Quick comparison of legacy :ref:`mtrand <legacy>` to the new `Generator`
================== ==================== =============
Feature Older Equivalent Notes
@@ -52,7 +52,7 @@ And in more detail:
methods which are 2-10 times faster than NumPy's default implementation in
`~.Generator.standard_normal`, `~.Generator.standard_exponential` or
`~.Generator.standard_gamma`.
-
+
.. ipython:: python
diff --git a/doc/source/reference/ufuncs.rst b/doc/source/reference/ufuncs.rst
index 6d58d1a6d..8f506dd8b 100644
--- a/doc/source/reference/ufuncs.rst
+++ b/doc/source/reference/ufuncs.rst
@@ -109,7 +109,7 @@ The output of the ufunc (and its methods) is not necessarily an
:class:`ndarray`, if all input arguments are not :class:`ndarrays <ndarray>`.
Indeed, if any input defines an :obj:`~class.__array_ufunc__` method,
control will be passed completely to that function, i.e., the ufunc is
-`overridden <ufuncs.overrides>`_.
+:ref:`overridden <ufuncs.overrides>`.
If none of the inputs overrides the ufunc, then
all output arrays will be passed to the :obj:`~class.__array_prepare__` and
diff --git a/doc/source/release/1.19.0-notes.rst b/doc/source/release/1.19.0-notes.rst
index ea0ac6193..b40969550 100644
--- a/doc/source/release/1.19.0-notes.rst
+++ b/doc/source/release/1.19.0-notes.rst
@@ -24,14 +24,14 @@ Calling ``np.array([[1, [1, 2, 3]])`` will issue a ``DeprecationWarning`` as
per `NEP 34`_. Users should explicitly use ``dtype=object`` to avoid the
warning.
-.. _`NEP 34`: https://numpy.org/neps/nep-0034.html
+.. _`NEP 34`: https://numpy.org/neps/nep-0034-infer-dtype-is-object.html
(`gh-15119 <https://github.com/numpy/numpy/pull/15119>`__)
Passing ``shape=0`` to factory functions in ``numpy.rec`` is deprecated
-----------------------------------------------------------------------
-``0`` is treated as a special case and is aliased to ``None`` in the functions:
+``0`` is treated as a special case and is aliased to ``None`` in the functions:
* `numpy.core.records.fromarrays`
* `numpy.core.records.fromrecords`
@@ -267,6 +267,19 @@ of users.
(`gh-16068 <https://github.com/numpy/numpy/pull/16068>`__)
+``SeedSequence`` with small seeds no longer conflicts with spawning
+-------------------------------------------------------------------
+Small seeds (less than ``2**96``) are implicitly 0-padded out to 128 bits, the
+size of the internal entropy pool. When spawned, the spawn key was concatenated
+before the 0-padding. Since the first spawn key is ``(0,)``, small seeds
+before the spawn created the same states as the first spawned ``SeedSequence``.
+Now, the seed is explicitly 0-padded out to the internal pool size before
+concatenating the spawn key. Spawned ``SeedSequences`` will produce different
+results than in the previous release. Unspawned ``SeedSequences`` will still
+produce the same results.
+
+(`gh-16551 <https://github.com/numpy/numpy/pull/16551>`__)
+
C API changes
=============
@@ -284,12 +297,12 @@ functions.
(`gh-15251 <https://github.com/numpy/numpy/pull/15251>`__)
-Const qualify UFunc inner loops
--------------------------------
-``UFuncGenericFunction`` now expects pointers to const ``dimension`` and
-``strides`` as arguments. This means inner loops may no longer modify
-either ``dimension`` or ``strides``. This change leads to an
-``incompatible-pointer-types`` warning forcing users to either ignore
+Const qualify UFunc inner loops
+-------------------------------
+``UFuncGenericFunction`` now expects pointers to const ``dimension`` and
+``strides`` as arguments. This means inner loops may no longer modify
+either ``dimension`` or ``strides``. This change leads to an
+``incompatible-pointer-types`` warning forcing users to either ignore
the compiler warnings or to const qualify their own loop signatures.
(`gh-15355 <https://github.com/numpy/numpy/pull/15355>`__)
@@ -316,12 +329,12 @@ now expose this through the buffer interface, meaning
``subok`` option for `numpy.copy`
---------------------------------
-A new kwarg, ``subok``, was added to `numpy.copy` to allow users to toggle the
+A new kwarg, ``subok``, was added to `numpy.copy` to allow users to toggle the
behavior of `numpy.copy` with respect to array subclasses. The default value
-is ``False`` which is consistent with the behavior of `numpy.copy` for
+is ``False`` which is consistent with the behavior of `numpy.copy` for
previous numpy versions. To create a copy that preserves an array subclass with
`numpy.copy`, call ``np.copy(arr, subok=True)``. This addition better documents
-that the default behavior of `numpy.copy` differs from the
+that the default behavior of `numpy.copy` differs from the
`numpy.ndarray.copy` method which respects array subclasses by default.
(`gh-15685 <https://github.com/numpy/numpy/pull/15685>`__)
@@ -345,8 +358,8 @@ as `numpy.sum` or `numpy.mean`.
``equal_nan`` parameter for `numpy.array_equal`
------------------------------------------------
The keyword argument ``equal_nan`` was added to `numpy.array_equal`.
-``equal_nan`` is a boolean value that toggles whether or not ``nan`` values
-are considered equal in comparison (default is ``False``). This matches API
+``equal_nan`` is a boolean value that toggles whether or not ``nan`` values
+are considered equal in comparison (default is ``False``). This matches API
used in related functions such as `numpy.isclose` and `numpy.allclose`.
(`gh-16128 <https://github.com/numpy/numpy/pull/16128>`__)
@@ -376,9 +389,9 @@ linear algebra for large arrays.
Use AVX512 intrinsic to implement ``np.exp`` when input is ``np.float64``
--------------------------------------------------------------------------
-Use AVX512 intrinsic to implement ``np.exp`` when input is ``np.float64``,
+Use AVX512 intrinsic to implement ``np.exp`` when input is ``np.float64``,
which can improve the performance of ``np.exp`` with ``np.float64`` input 5-7x
-faster than before. The _multiarray_umath.so module has grown about 63 KB on
+faster than before. The _multiarray_umath.so module has grown about 63 KB on
linux64.
(`gh-15648 <https://github.com/numpy/numpy/pull/15648>`__)
diff --git a/doc/source/release/1.5.0-notes.rst b/doc/source/release/1.5.0-notes.rst
index a2184ab13..2b0c32f3e 100644
--- a/doc/source/release/1.5.0-notes.rst
+++ b/doc/source/release/1.5.0-notes.rst
@@ -12,11 +12,11 @@ Python 3 compatibility
This is the first NumPy release which is compatible with Python 3. Support for
Python 3 and Python 2 is done from a single code base. Extensive notes on
changes can be found at
-`<http://projects.scipy.org/numpy/browser/trunk/doc/Py3K.txt>`_.
+`<https://web.archive.org/web/20100814160313/http://projects.scipy.org/numpy/browser/trunk/doc/Py3K.txt>`_.
Note that the Numpy testing framework relies on nose, which does not have a
Python 3 compatible release yet. A working Python 3 branch of nose can be found
-at `<http://bitbucket.org/jpellerin/nose3/>`_ however.
+at `<https://web.archive.org/web/20100817112505/http://bitbucket.org/jpellerin/nose3/>`_ however.
Porting of SciPy to Python 3 is expected to be completed soon.
diff --git a/doc/source/user/absolute_beginners.rst b/doc/source/user/absolute_beginners.rst
index bd44b70da..5873eb108 100644
--- a/doc/source/user/absolute_beginners.rst
+++ b/doc/source/user/absolute_beginners.rst
@@ -1531,19 +1531,19 @@ Importing and exporting a CSV
-----------------------------
.. save a csv
-
+
>>> with open('music.csv', 'w') as fid:
... n = fid.write('Artist,Genre,Listeners,Plays\n')
... n = fid.write('Billie Holiday,Jazz,1300000,27000000\n')
... n = fid.write('Jimmie Hendrix,Rock,2700000,70000000\n')
... n = fid.write('Miles Davis,Jazz,1500000,48000000\n')
... n = fid.write('SIA,Pop,2000000,74000000\n')
-
+
It's simple to read in a CSV that contains existing information. The best and
easiest way to do this is to use
-`Pandas <https://pandas.pydata.org/getpandas.html>`_. ::
+`Pandas <https://pandas.pydata.org>`_. ::
>>> import pandas as pd
diff --git a/doc/source/user/building.rst b/doc/source/user/building.rst
index 47a0a03c9..6a880b59e 100644
--- a/doc/source/user/building.rst
+++ b/doc/source/user/building.rst
@@ -6,6 +6,10 @@ Building from source
A general overview of building NumPy from source is given here, with detailed
instructions for specific platforms given separately.
+..
+ This page is referenced from numpy/numpy/__init__.py. Please keep its
+ location in sync with the link there.
+
Prerequisites
-------------
@@ -159,6 +163,14 @@ will prefer to use ATLAS, then OpenBLAS and as a last resort MKL.
If neither of these exists the build will fail (names are compared
lower case).
+.. deprecated:: 1.20
+ The native libraries on macOS, provided by Accelerate, are not fit for use
+ in NumPy since they have bugs that cause wrong output under easily reproducible
+ conditions. If the vendor fixes those bugs, the library could be reinstated,
+ but until then users compiling for themselves should use another linear
+ algebra library or use the built-in (but slower) default, see the next
+ section.
+
Disabling ATLAS and other accelerated libraries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/source/user/quickstart.rst b/doc/source/user/quickstart.rst
index 29a4d80ca..b1af81886 100644
--- a/doc/source/user/quickstart.rst
+++ b/doc/source/user/quickstart.rst
@@ -22,7 +22,7 @@ https://scipy.org/install.html for instructions.
**Learner profile**
-This tutorial is intended as a quick overview of
+This tutorial is intended as a quick overview of
algebra and arrays in NumPy and want to understand how n-dimensional
(:math:`n>=2`) arrays are represented and can be manipulated. In particular, if
you don't know how to apply common functions to n-dimensional arrays (without
@@ -1036,6 +1036,8 @@ Basic Linear Algebra
Less Basic
==========
+.. _broadcasting-rules:
+
Broadcasting rules
------------------
@@ -1054,7 +1056,7 @@ element is assumed to be the same along that dimension for the
"broadcast" array.
After application of the broadcasting rules, the sizes of all arrays
-must match. More details can be found in :doc:`basics.broadcasting`.
+must match. More details can be found in :ref:`basics.broadcasting`.
Advanced indexing and index tricks
==================================
@@ -1390,8 +1392,8 @@ and then use it as::
[14, 13, 15, 17, 12]]])
The advantage of this version of reduce compared to the normal
-ufunc.reduce is that it makes use of the `Broadcasting
-Rules <Tentative_NumPy_Tutorial.html#head-c43f3f81719d84f09ae2b33a22eaf50b26333db8>`__
+ufunc.reduce is that it makes use of the
+:ref:`broadcasting rules <broadcasting-rules>`
in order to avoid creating an argument array the size of the output
times the number of vectors.
diff --git a/numpy/__init__.py b/numpy/__init__.py
index e6a24f0d1..1c3b11844 100644
--- a/numpy/__init__.py
+++ b/numpy/__init__.py
@@ -279,12 +279,11 @@ else:
error_message = "{}: {}".format(w[-1].category.__name__, str(w[-1].message))
msg = (
"Polyfit sanity test emitted a warning, most likely due "
- "to using a buggy Accelerate backend. "
- "If you compiled yourself, "
- "see site.cfg.example for information. "
+ "to using a buggy Accelerate backend. If you compiled "
+ "yourself, more information is available at "
+ "https://numpy.org/doc/stable/user/building.html#accelerated-blas-lapack-libraries "
"Otherwise report this to the vendor "
- "that provided NumPy.\n{}\n".format(
- error_message))
+ "that provided NumPy.\n{}\n".format(error_message))
raise RuntimeError(msg)
del _mac_os_check
diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi
new file mode 100644
index 000000000..f9218391e
--- /dev/null
+++ b/numpy/__init__.pyi
@@ -0,0 +1,1062 @@
+import builtins
+import sys
+import datetime as dt
+from abc import abstractmethod
+
+from numpy.core._internal import _ctypes
+from numpy.typing import ArrayLike, DtypeLike, _Shape, _ShapeLike
+
+from typing import (
+ Any,
+ ByteString,
+ Callable,
+ Container,
+ Callable,
+ Dict,
+ Generic,
+ IO,
+ Iterable,
+ List,
+ Mapping,
+ Optional,
+ overload,
+ Sequence,
+ Sized,
+ SupportsAbs,
+ SupportsComplex,
+ SupportsFloat,
+ SupportsInt,
+ Text,
+ Tuple,
+ Type,
+ TypeVar,
+ Union,
+)
+
+if sys.version_info[0] < 3:
+ class SupportsBytes: ...
+
+else:
+ from typing import SupportsBytes
+
+if sys.version_info >= (3, 8):
+ from typing import Literal, Protocol
+else:
+ from typing_extensions import Literal, Protocol
+
+# TODO: remove when the full numpy namespace is defined
+def __getattr__(name: str) -> Any: ...
+
+_NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray)
+
+class dtype:
+ names: Optional[Tuple[str, ...]]
+ def __init__(
+ self,
+ dtype: DtypeLike,
+ align: bool = ...,
+ copy: bool = ...,
+ ) -> None: ...
+ def __eq__(self, other: DtypeLike) -> bool: ...
+ def __ne__(self, other: DtypeLike) -> bool: ...
+ def __gt__(self, other: DtypeLike) -> bool: ...
+ def __ge__(self, other: DtypeLike) -> bool: ...
+ def __lt__(self, other: DtypeLike) -> bool: ...
+ def __le__(self, other: DtypeLike) -> bool: ...
+ @property
+ def alignment(self) -> int: ...
+ @property
+ def base(self) -> dtype: ...
+ @property
+ def byteorder(self) -> str: ...
+ @property
+ def char(self) -> str: ...
+ @property
+ def descr(self) -> List[Union[Tuple[str, str], Tuple[str, str, _Shape]]]: ...
+ @property
+ def fields(
+ self,
+ ) -> Optional[Mapping[str, Union[Tuple[dtype, int], Tuple[dtype, int, Any]]]]: ...
+ @property
+ def flags(self) -> int: ...
+ @property
+ def hasobject(self) -> bool: ...
+ @property
+ def isbuiltin(self) -> int: ...
+ @property
+ def isnative(self) -> bool: ...
+ @property
+ def isalignedstruct(self) -> bool: ...
+ @property
+ def itemsize(self) -> int: ...
+ @property
+ def kind(self) -> str: ...
+ @property
+ def metadata(self) -> Optional[Mapping[str, Any]]: ...
+ @property
+ def name(self) -> str: ...
+ @property
+ def num(self) -> int: ...
+ @property
+ def shape(self) -> _Shape: ...
+ @property
+ def ndim(self) -> int: ...
+ @property
+ def subdtype(self) -> Optional[Tuple[dtype, _Shape]]: ...
+ def newbyteorder(self, new_order: str = ...) -> dtype: ...
+ # Leave str and type for end to avoid having to use `builtins.str`
+ # everywhere. See https://github.com/python/mypy/issues/3775
+ @property
+ def str(self) -> builtins.str: ...
+ @property
+ def type(self) -> Type[generic]: ...
+
+_Dtype = dtype # to avoid name conflicts with ndarray.dtype
+
+class _flagsobj:
+ aligned: bool
+ updateifcopy: bool
+ writeable: bool
+ writebackifcopy: bool
+ @property
+ def behaved(self) -> bool: ...
+ @property
+ def c_contiguous(self) -> bool: ...
+ @property
+ def carray(self) -> bool: ...
+ @property
+ def contiguous(self) -> bool: ...
+ @property
+ def f_contiguous(self) -> bool: ...
+ @property
+ def farray(self) -> bool: ...
+ @property
+ def fnc(self) -> bool: ...
+ @property
+ def forc(self) -> bool: ...
+ @property
+ def fortran(self) -> bool: ...
+ @property
+ def num(self) -> int: ...
+ @property
+ def owndata(self) -> bool: ...
+ def __getitem__(self, key: str) -> bool: ...
+ def __setitem__(self, key: str, value: bool) -> None: ...
+
+_FlatIterSelf = TypeVar("_FlatIterSelf", bound=flatiter)
+
+class flatiter(Generic[_ArraySelf]):
+ @property
+ def base(self) -> _ArraySelf: ...
+ @property
+ def coords(self) -> _Shape: ...
+ @property
+ def index(self) -> int: ...
+ def copy(self) -> _ArraySelf: ...
+ def __iter__(self: _FlatIterSelf) -> _FlatIterSelf: ...
+ def __next__(self) -> generic: ...
+
+_ArraySelf = TypeVar("_ArraySelf", bound=_ArrayOrScalarCommon)
+
+class _ArrayOrScalarCommon(
+ SupportsInt, SupportsFloat, SupportsComplex, SupportsBytes, SupportsAbs[Any]
+):
+ @property
+ def T(self: _ArraySelf) -> _ArraySelf: ...
+ @property
+ def base(self) -> Optional[ndarray]: ...
+ @property
+ def dtype(self) -> _Dtype: ...
+ @property
+ def data(self) -> memoryview: ...
+ @property
+ def flags(self) -> _flagsobj: ...
+ @property
+ def size(self) -> int: ...
+ @property
+ def itemsize(self) -> int: ...
+ @property
+ def nbytes(self) -> int: ...
+ @property
+ def ndim(self) -> int: ...
+ @property
+ def shape(self) -> _Shape: ...
+ @property
+ def strides(self) -> _Shape: ...
+ def __array__(self, __dtype: DtypeLike = ...) -> ndarray: ...
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+ if sys.version_info[0] < 3:
+ def __oct__(self) -> str: ...
+ def __hex__(self) -> str: ...
+ def __nonzero__(self) -> bool: ...
+ def __unicode__(self) -> Text: ...
+ else:
+ def __bool__(self) -> bool: ...
+ def __bytes__(self) -> bytes: ...
+ def __str__(self) -> str: ...
+ def __repr__(self) -> str: ...
+ def __copy__(self: _ArraySelf, order: str = ...) -> _ArraySelf: ...
+ def __deepcopy__(self: _ArraySelf, memo: dict) -> _ArraySelf: ...
+ def __lt__(self, other): ...
+ def __le__(self, other): ...
+ def __eq__(self, other): ...
+ def __ne__(self, other): ...
+ def __gt__(self, other): ...
+ def __ge__(self, other): ...
+ def __add__(self, other): ...
+ def __radd__(self, other): ...
+ def __iadd__(self, other): ...
+ def __sub__(self, other): ...
+ def __rsub__(self, other): ...
+ def __isub__(self, other): ...
+ def __mul__(self, other): ...
+ def __rmul__(self, other): ...
+ def __imul__(self, other): ...
+ if sys.version_info[0] < 3:
+ def __div__(self, other): ...
+ def __rdiv__(self, other): ...
+ def __idiv__(self, other): ...
+ def __truediv__(self, other): ...
+ def __rtruediv__(self, other): ...
+ def __itruediv__(self, other): ...
+ def __floordiv__(self, other): ...
+ def __rfloordiv__(self, other): ...
+ def __ifloordiv__(self, other): ...
+ def __mod__(self, other): ...
+ def __rmod__(self, other): ...
+ def __imod__(self, other): ...
+ def __divmod__(self, other): ...
+ def __rdivmod__(self, other): ...
+ # NumPy's __pow__ doesn't handle a third argument
+ def __pow__(self, other): ...
+ def __rpow__(self, other): ...
+ def __ipow__(self, other): ...
+ def __lshift__(self, other): ...
+ def __rlshift__(self, other): ...
+ def __ilshift__(self, other): ...
+ def __rshift__(self, other): ...
+ def __rrshift__(self, other): ...
+ def __irshift__(self, other): ...
+ def __and__(self, other): ...
+ def __rand__(self, other): ...
+ def __iand__(self, other): ...
+ def __xor__(self, other): ...
+ def __rxor__(self, other): ...
+ def __ixor__(self, other): ...
+ def __or__(self, other): ...
+ def __ror__(self, other): ...
+ def __ior__(self, other): ...
+ if sys.version_info[:2] >= (3, 5):
+ def __matmul__(self, other): ...
+ def __rmatmul__(self, other): ...
+ def __neg__(self: _ArraySelf) -> _ArraySelf: ...
+ def __pos__(self: _ArraySelf) -> _ArraySelf: ...
+ def __abs__(self: _ArraySelf) -> _ArraySelf: ...
+ def __invert__(self: _ArraySelf) -> _ArraySelf: ...
+ # TODO(shoyer): remove when all methods are defined
+ def __getattr__(self, name) -> Any: ...
+
+_BufferType = Union[ndarray, bytes, bytearray, memoryview]
+
+class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container):
+ @property
+ def real(self: _ArraySelf) -> _ArraySelf: ...
+ @real.setter
+ def real(self, value: ArrayLike) -> None: ...
+ @property
+ def imag(self: _ArraySelf) -> _ArraySelf: ...
+ @imag.setter
+ def imag(self, value: ArrayLike) -> None: ...
+ def __new__(
+ cls: Type[_ArraySelf],
+ shape: Sequence[int],
+ dtype: DtypeLike = ...,
+ buffer: _BufferType = ...,
+ offset: int = ...,
+ strides: _ShapeLike = ...,
+ order: Optional[str] = ...,
+ ) -> _ArraySelf: ...
+ @property
+ def dtype(self) -> _Dtype: ...
+ @property
+ def ctypes(self) -> _ctypes: ...
+ @property
+ def shape(self) -> _Shape: ...
+ @shape.setter
+ def shape(self, value: _ShapeLike): ...
+ @property
+ def flat(self: _ArraySelf) -> flatiter[_ArraySelf]: ...
+ @property
+ def strides(self) -> _Shape: ...
+ @strides.setter
+ def strides(self, value: _ShapeLike): ...
+ # Array conversion
+ @overload
+ def item(self, *args: int) -> Any: ...
+ @overload
+ def item(self, args: Tuple[int, ...]) -> Any: ...
+ def tolist(self) -> List[Any]: ...
+ @overload
+ def itemset(self, __value: Any) -> None: ...
+ @overload
+ def itemset(self, __item: _ShapeLike, __value: Any) -> None: ...
+ def tobytes(self, order: Optional[str] = ...) -> bytes: ...
+ def tofile(
+ self, fid: Union[IO[bytes], str], sep: str = ..., format: str = ...
+ ) -> None: ...
+ def dump(self, file: str) -> None: ...
+ def dumps(self) -> bytes: ...
+ def astype(
+ self: _ArraySelf,
+ dtype: DtypeLike,
+ order: str = ...,
+ casting: str = ...,
+ subok: bool = ...,
+ copy: bool = ...,
+ ) -> _ArraySelf: ...
+ def byteswap(self: _ArraySelf, inplace: bool = ...) -> _ArraySelf: ...
+ def copy(self: _ArraySelf, order: str = ...) -> _ArraySelf: ...
+ @overload
+ def view(self, type: Type[_NdArraySubClass]) -> _NdArraySubClass: ...
+ @overload
+ def view(self: _ArraySelf, dtype: DtypeLike = ...) -> _ArraySelf: ...
+ @overload
+ def view(
+ self, dtype: DtypeLike, type: Type[_NdArraySubClass]
+ ) -> _NdArraySubClass: ...
+ def getfield(
+ self: _ArraySelf, dtype: DtypeLike, offset: int = ...
+ ) -> _ArraySelf: ...
+ def setflags(
+ self, write: bool = ..., align: bool = ..., uic: bool = ...
+ ) -> None: ...
+ def fill(self, value: Any) -> None: ...
+ # Shape manipulation
+ @overload
+ def reshape(
+ self: _ArraySelf, shape: Sequence[int], *, order: str = ...
+ ) -> _ArraySelf: ...
+ @overload
+ def reshape(self: _ArraySelf, *shape: int, order: str = ...) -> _ArraySelf: ...
+ @overload
+ def resize(self, new_shape: Sequence[int], *, refcheck: bool = ...) -> None: ...
+ @overload
+ def resize(self, *new_shape: int, refcheck: bool = ...) -> None: ...
+ @overload
+ def transpose(self: _ArraySelf, axes: Sequence[int]) -> _ArraySelf: ...
+ @overload
+ def transpose(self: _ArraySelf, *axes: int) -> _ArraySelf: ...
+ def swapaxes(self: _ArraySelf, axis1: int, axis2: int) -> _ArraySelf: ...
+ def flatten(self: _ArraySelf, order: str = ...) -> _ArraySelf: ...
+ def ravel(self: _ArraySelf, order: str = ...) -> _ArraySelf: ...
+ def squeeze(
+ self: _ArraySelf, axis: Union[int, Tuple[int, ...]] = ...
+ ) -> _ArraySelf: ...
+ # Many of these special methods are irrelevant currently, since protocols
+ # aren't supported yet. That said, I'm adding them for completeness.
+ # https://docs.python.org/3/reference/datamodel.html
+ def __len__(self) -> int: ...
+ def __getitem__(self, key) -> Any: ...
+ def __setitem__(self, key, value): ...
+ def __iter__(self) -> Any: ...
+ def __contains__(self, key) -> bool: ...
+ def __index__(self) -> int: ...
+
+# NOTE: while `np.generic` is not technically an instance of `ABCMeta`,
+# the `@abstractmethod` decorator is herein used to (forcefully) deny
+# the creation of `np.generic` instances.
+# The `# type: ignore` comments are necessary to silence mypy errors regarding
+# the missing `ABCMeta` metaclass.
+
+# See https://github.com/numpy/numpy-stubs/pull/80 for more details.
+
+class generic(_ArrayOrScalarCommon):
+ @abstractmethod
+ def __init__(self, *args: Any, **kwargs: Any) -> None: ...
+ @property
+ def base(self) -> None: ...
+
+class _real_generic(generic): # type: ignore
+ @property
+ def real(self: _ArraySelf) -> _ArraySelf: ...
+ @property
+ def imag(self: _ArraySelf) -> _ArraySelf: ...
+
+class number(generic): ... # type: ignore
+
+class bool_(_real_generic):
+ def __init__(self, __value: object = ...) -> None: ...
+
+class object_(generic):
+ def __init__(self, __value: object = ...) -> None: ...
+
+class datetime64:
+ @overload
+ def __init__(
+ self, __value: Union[datetime64, str, dt.datetime] = ..., __format: str = ...
+ ) -> None: ...
+ @overload
+ def __init__(self, __value: int, __format: str) -> None: ...
+ def __add__(self, other: Union[timedelta64, int]) -> datetime64: ...
+ def __sub__(self, other: Union[timedelta64, datetime64, int]) -> timedelta64: ...
+
+class integer(number, _real_generic): ... # type: ignore
+class signedinteger(integer): ... # type: ignore
+
+class int8(signedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class int16(signedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class int32(signedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class int64(signedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class timedelta64(signedinteger):
+ def __init__(self, __value: Any = ..., __format: str = ...) -> None: ...
+ @overload
+ def __add__(self, other: Union[timedelta64, int]) -> timedelta64: ...
+ @overload
+ def __add__(self, other: datetime64) -> datetime64: ...
+ def __sub__(self, other: Union[timedelta64, int]) -> timedelta64: ...
+ if sys.version_info[0] < 3:
+ @overload
+ def __div__(self, other: timedelta64) -> float: ...
+ @overload
+ def __div__(self, other: float) -> timedelta64: ...
+ @overload
+ def __truediv__(self, other: timedelta64) -> float: ...
+ @overload
+ def __truediv__(self, other: float) -> timedelta64: ...
+ def __mod__(self, other: timedelta64) -> timedelta64: ...
+
+class unsignedinteger(integer): ... # type: ignore
+
+class uint8(unsignedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class uint16(unsignedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class uint32(unsignedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class uint64(unsignedinteger):
+ def __init__(self, __value: SupportsInt = ...) -> None: ...
+
+class inexact(number): ... # type: ignore
+class floating(inexact, _real_generic): ... # type: ignore
+
+class float16(floating):
+ def __init__(self, __value: SupportsFloat = ...) -> None: ...
+
+class float32(floating):
+ def __init__(self, __value: SupportsFloat = ...) -> None: ...
+
+class float64(floating):
+ def __init__(self, __value: SupportsFloat = ...) -> None: ...
+
+class complexfloating(inexact): ... # type: ignore
+
+class complex64(complexfloating):
+ def __init__(
+ self, __value: Union[SupportsInt, SupportsFloat, SupportsComplex] = ...
+ ) -> None: ...
+ @property
+ def real(self) -> float32: ...
+ @property
+ def imag(self) -> float32: ...
+
+class complex128(complexfloating):
+ def __init__(
+ self, __value: Union[SupportsInt, SupportsFloat, SupportsComplex] = ...
+ ) -> None: ...
+ @property
+ def real(self) -> float64: ...
+ @property
+ def imag(self) -> float64: ...
+
+class flexible(_real_generic): ... # type: ignore
+
+class void(flexible):
+ def __init__(self, __value: Union[int, integer, bool_, bytes, bytes_]): ...
+
+class character(_real_generic): ... # type: ignore
+
+class bytes_(character):
+ @overload
+ def __init__(self, __value: object = ...) -> None: ...
+ @overload
+ def __init__(
+ self, __value: Union[str, str_], encoding: str = ..., errors: str = ...
+ ) -> None: ...
+
+class str_(character):
+ @overload
+ def __init__(self, __value: object = ...) -> None: ...
+ @overload
+ def __init__(
+ self, __value: Union[bytes, bytes_], encoding: str = ..., errors: str = ...
+ ) -> None: ...
+
+# TODO(alan): Platform dependent types
+# longcomplex, longdouble, longfloat
+# bytes, short, intc, intp, longlong
+# half, single, double, longdouble
+# uint_, int_, float_, complex_
+# float128, complex256
+# float96
+
+def array(
+ object: object,
+ dtype: DtypeLike = ...,
+ copy: bool = ...,
+ subok: bool = ...,
+ ndmin: int = ...,
+) -> ndarray: ...
+def zeros(
+ shape: _ShapeLike, dtype: DtypeLike = ..., order: Optional[str] = ...
+) -> ndarray: ...
+def ones(
+ shape: _ShapeLike, dtype: DtypeLike = ..., order: Optional[str] = ...
+) -> ndarray: ...
+def empty(
+ shape: _ShapeLike, dtype: DtypeLike = ..., order: Optional[str] = ...
+) -> ndarray: ...
+def zeros_like(
+ a: ArrayLike,
+ dtype: DtypeLike = ...,
+ order: str = ...,
+ subok: bool = ...,
+ shape: Optional[Union[int, Sequence[int]]] = ...,
+) -> ndarray: ...
+def ones_like(
+ a: ArrayLike,
+ dtype: DtypeLike = ...,
+ order: str = ...,
+ subok: bool = ...,
+ shape: Optional[_ShapeLike] = ...,
+) -> ndarray: ...
+def empty_like(
+ a: ArrayLike,
+ dtype: DtypeLike = ...,
+ order: str = ...,
+ subok: bool = ...,
+ shape: Optional[_ShapeLike] = ...,
+) -> ndarray: ...
+def full(
+ shape: _ShapeLike, fill_value: Any, dtype: DtypeLike = ..., order: str = ...
+) -> ndarray: ...
+def full_like(
+ a: ArrayLike,
+ fill_value: Any,
+ dtype: DtypeLike = ...,
+ order: str = ...,
+ subok: bool = ...,
+ shape: Optional[_ShapeLike] = ...,
+) -> ndarray: ...
+def count_nonzero(
+ a: ArrayLike, axis: Optional[Union[int, Tuple[int], Tuple[int, int]]] = ...
+) -> Union[int, ndarray]: ...
+def isfortran(a: ndarray) -> bool: ...
+def argwhere(a: ArrayLike) -> ndarray: ...
+def flatnonzero(a: ArrayLike) -> ndarray: ...
+def correlate(a: ArrayLike, v: ArrayLike, mode: str = ...) -> ndarray: ...
+def convolve(a: ArrayLike, v: ArrayLike, mode: str = ...) -> ndarray: ...
+def outer(a: ArrayLike, b: ArrayLike, out: ndarray = ...) -> ndarray: ...
+def tensordot(
+ a: ArrayLike,
+ b: ArrayLike,
+ axes: Union[
+ int, Tuple[int, int], Tuple[Tuple[int, int], ...], Tuple[List[int, int], ...]
+ ] = ...,
+) -> ndarray: ...
+def roll(
+ a: ArrayLike,
+ shift: Union[int, Tuple[int, ...]],
+ axis: Optional[Union[int, Tuple[int, ...]]] = ...,
+) -> ndarray: ...
+def rollaxis(a: ArrayLike, axis: int, start: int = ...) -> ndarray: ...
+def moveaxis(
+ a: ndarray,
+ source: Union[int, Sequence[int]],
+ destination: Union[int, Sequence[int]],
+) -> ndarray: ...
+def cross(
+ a: ArrayLike,
+ b: ArrayLike,
+ axisa: int = ...,
+ axisb: int = ...,
+ axisc: int = ...,
+ axis: Optional[int] = ...,
+) -> ndarray: ...
+def indices(
+ dimensions: Sequence[int], dtype: dtype = ..., sparse: bool = ...
+) -> Union[ndarray, Tuple[ndarray, ...]]: ...
+def fromfunction(function: Callable, shape: Tuple[int, int], **kwargs) -> Any: ...
+def isscalar(element: Any) -> bool: ...
+def binary_repr(num: int, width: Optional[int] = ...) -> str: ...
+def base_repr(number: int, base: int = ..., padding: int = ...) -> str: ...
+def identity(n: int, dtype: DtypeLike = ...) -> ndarray: ...
+def allclose(
+ a: ArrayLike,
+ b: ArrayLike,
+ rtol: float = ...,
+ atol: float = ...,
+ equal_nan: bool = ...,
+) -> bool: ...
+def isclose(
+ a: ArrayLike,
+ b: ArrayLike,
+ rtol: float = ...,
+ atol: float = ...,
+ equal_nan: bool = ...,
+) -> Union[bool_, ndarray]: ...
+def array_equal(a1: ArrayLike, a2: ArrayLike) -> bool: ...
+def array_equiv(a1: ArrayLike, a2: ArrayLike) -> bool: ...
+
+#
+# Constants
+#
+
+Inf: float
+Infinity: float
+NAN: float
+NINF: float
+NZERO: float
+NaN: float
+PINF: float
+PZERO: float
+e: float
+euler_gamma: float
+inf: float
+infty: float
+nan: float
+pi: float
+
+ALLOW_THREADS: int
+BUFSIZE: int
+CLIP: int
+ERR_CALL: int
+ERR_DEFAULT: int
+ERR_IGNORE: int
+ERR_LOG: int
+ERR_PRINT: int
+ERR_RAISE: int
+ERR_WARN: int
+FLOATING_POINT_SUPPORT: int
+FPE_DIVIDEBYZERO: int
+FPE_INVALID: int
+FPE_OVERFLOW: int
+FPE_UNDERFLOW: int
+MAXDIMS: int
+MAY_SHARE_BOUNDS: int
+MAY_SHARE_EXACT: int
+RAISE: int
+SHIFT_DIVIDEBYZERO: int
+SHIFT_INVALID: int
+SHIFT_OVERFLOW: int
+SHIFT_UNDERFLOW: int
+UFUNC_BUFSIZE_DEFAULT: int
+WRAP: int
+little_endian: int
+tracemalloc_domain: int
+
+class ufunc:
+ @property
+ def __name__(self) -> str: ...
+ def __call__(
+ self,
+ *args: ArrayLike,
+ out: Optional[Union[ndarray, Tuple[ndarray, ...]]] = ...,
+ where: Optional[ndarray] = ...,
+ # The list should be a list of tuples of ints, but since we
+ # don't know the signature it would need to be
+ # Tuple[int, ...]. But, since List is invariant something like
+ # e.g. List[Tuple[int, int]] isn't a subtype of
+ # List[Tuple[int, ...]], so we can't type precisely here.
+ axes: List[Any] = ...,
+ axis: int = ...,
+ keepdims: bool = ...,
+ # TODO: make this precise when we can use Literal.
+ casting: str = ...,
+ # TODO: make this precise when we can use Literal.
+ order: Optional[str] = ...,
+ dtype: DtypeLike = ...,
+ subok: bool = ...,
+ signature: Union[str, Tuple[str]] = ...,
+ # In reality this should be a length of list 3 containing an
+ # int, an int, and a callable, but there's no way to express
+ # that.
+ extobj: List[Union[int, Callable]] = ...,
+ ) -> Union[ndarray, generic]: ...
+ @property
+ def nin(self) -> int: ...
+ @property
+ def nout(self) -> int: ...
+ @property
+ def nargs(self) -> int: ...
+ @property
+ def ntypes(self) -> int: ...
+ @property
+ def types(self) -> List[str]: ...
+ # Broad return type because it has to encompass things like
+ #
+ # >>> np.logical_and.identity is True
+ # True
+ # >>> np.add.identity is 0
+ # True
+ # >>> np.sin.identity is None
+ # True
+ #
+ # and any user-defined ufuncs.
+ @property
+ def identity(self) -> Any: ...
+ # This is None for ufuncs and a string for gufuncs.
+ @property
+ def signature(self) -> Optional[str]: ...
+ # The next four methods will always exist, but they will just
+ # raise a ValueError ufuncs with that don't accept two input
+ # arguments and return one output argument. Because of that we
+ # can't type them very precisely.
+ @property
+ def reduce(self) -> Any: ...
+ @property
+ def accumulate(self) -> Any: ...
+ @property
+ def reduceat(self) -> Any: ...
+ @property
+ def outer(self) -> Any: ...
+ # Similarly at won't be defined for ufuncs that return multiple
+ # outputs, so we can't type it very precisely.
+ @property
+ def at(self) -> Any: ...
+
+absolute: ufunc
+add: ufunc
+arccos: ufunc
+arccosh: ufunc
+arcsin: ufunc
+arcsinh: ufunc
+arctan2: ufunc
+arctan: ufunc
+arctanh: ufunc
+bitwise_and: ufunc
+bitwise_or: ufunc
+bitwise_xor: ufunc
+cbrt: ufunc
+ceil: ufunc
+conjugate: ufunc
+copysign: ufunc
+cos: ufunc
+cosh: ufunc
+deg2rad: ufunc
+degrees: ufunc
+divmod: ufunc
+equal: ufunc
+exp2: ufunc
+exp: ufunc
+expm1: ufunc
+fabs: ufunc
+float_power: ufunc
+floor: ufunc
+floor_divide: ufunc
+fmax: ufunc
+fmin: ufunc
+fmod: ufunc
+frexp: ufunc
+gcd: ufunc
+greater: ufunc
+greater_equal: ufunc
+heaviside: ufunc
+hypot: ufunc
+invert: ufunc
+isfinite: ufunc
+isinf: ufunc
+isnan: ufunc
+isnat: ufunc
+lcm: ufunc
+ldexp: ufunc
+left_shift: ufunc
+less: ufunc
+less_equal: ufunc
+log10: ufunc
+log1p: ufunc
+log2: ufunc
+log: ufunc
+logaddexp2: ufunc
+logaddexp: ufunc
+logical_and: ufunc
+logical_not: ufunc
+logical_or: ufunc
+logical_xor: ufunc
+matmul: ufunc
+maximum: ufunc
+minimum: ufunc
+modf: ufunc
+multiply: ufunc
+negative: ufunc
+nextafter: ufunc
+not_equal: ufunc
+positive: ufunc
+power: ufunc
+rad2deg: ufunc
+radians: ufunc
+reciprocal: ufunc
+remainder: ufunc
+right_shift: ufunc
+rint: ufunc
+sign: ufunc
+signbit: ufunc
+sin: ufunc
+sinh: ufunc
+spacing: ufunc
+sqrt: ufunc
+square: ufunc
+subtract: ufunc
+tan: ufunc
+tanh: ufunc
+true_divide: ufunc
+trunc: ufunc
+
+# Warnings
+class ModuleDeprecationWarning(DeprecationWarning): ...
+class VisibleDeprecationWarning(UserWarning): ...
+class ComplexWarning(RuntimeWarning): ...
+class RankWarning(UserWarning): ...
+
+# Errors
+class TooHardError(RuntimeError): ...
+
+class AxisError(ValueError, IndexError):
+ def __init__(
+ self, axis: int, ndim: Optional[int] = ..., msg_prefix: Optional[str] = ...
+ ) -> None: ...
+
+# Functions from np.core.numerictypes
+_DefaultType = TypeVar("_DefaultType")
+
+def maximum_sctype(t: DtypeLike) -> dtype: ...
+def issctype(rep: object) -> bool: ...
+@overload
+def obj2sctype(rep: object) -> Optional[generic]: ...
+@overload
+def obj2sctype(rep: object, default: None) -> Optional[generic]: ...
+@overload
+def obj2sctype(
+ rep: object, default: Type[_DefaultType]
+) -> Union[generic, Type[_DefaultType]]: ...
+def issubclass_(arg1: object, arg2: Union[object, Tuple[object, ...]]) -> bool: ...
+def issubsctype(
+ arg1: Union[ndarray, DtypeLike], arg2: Union[ndarray, DtypeLike]
+) -> bool: ...
+def issubdtype(arg1: DtypeLike, arg2: DtypeLike) -> bool: ...
+def sctype2char(sctype: object) -> str: ...
+def find_common_type(
+ array_types: Sequence[DtypeLike], scalar_types: Sequence[DtypeLike]
+) -> dtype: ...
+
+# Functions from np.core.fromnumeric
+_Mode = Literal["raise", "wrap", "clip"]
+_Order = Literal["C", "F", "A"]
+_PartitionKind = Literal["introselect"]
+_SortKind = Literal["quicksort", "mergesort", "heapsort", "stable"]
+_Side = Literal["left", "right"]
+
+# Various annotations for scalars
+
+# While dt.datetime and dt.timedelta are not technically part of NumPy,
+# they are one of the rare few builtin scalars which serve as valid return types.
+# See https://github.com/numpy/numpy-stubs/pull/67#discussion_r412604113.
+_ScalarNumpy = Union[generic, dt.datetime, dt.timedelta]
+_ScalarBuiltin = Union[str, bytes, dt.date, dt.timedelta, bool, int, float, complex]
+_Scalar = Union[_ScalarBuiltin, _ScalarNumpy]
+
+# Integers and booleans can generally be used interchangeably
+_ScalarIntOrBool = TypeVar("_ScalarIntOrBool", bound=Union[integer, bool_])
+_ScalarGeneric = TypeVar("_ScalarGeneric", bound=generic)
+_ScalarGenericDT = TypeVar(
+ "_ScalarGenericDT", bound=Union[dt.datetime, dt.timedelta, generic]
+)
+
+# An array-like object consisting of integers
+_Int = Union[int, integer]
+_Bool = Union[bool, bool_]
+_IntOrBool = Union[_Int, _Bool]
+_ArrayLikeIntNested = ArrayLike # TODO: wait for support for recursive types
+_ArrayLikeBoolNested = ArrayLike # TODO: wait for support for recursive types
+
+# Integers and booleans can generally be used interchangeably
+_ArrayLikeIntOrBool = Union[
+ _IntOrBool,
+ ndarray,
+ Sequence[_IntOrBool],
+ Sequence[_ArrayLikeIntNested],
+ Sequence[_ArrayLikeBoolNested],
+]
+
+# The signature of take() follows a common theme with its overloads:
+# 1. A generic comes in; the same generic comes out
+# 2. A scalar comes in; a generic comes out
+# 3. An array-like object comes in; some keyword ensures that a generic comes out
+# 4. An array-like object comes in; an ndarray or generic comes out
+@overload
+def take(
+ a: _ScalarGenericDT,
+ indices: int,
+ axis: Optional[int] = ...,
+ out: Optional[ndarray] = ...,
+ mode: _Mode = ...,
+) -> _ScalarGenericDT: ...
+@overload
+def take(
+ a: _Scalar,
+ indices: int,
+ axis: Optional[int] = ...,
+ out: Optional[ndarray] = ...,
+ mode: _Mode = ...,
+) -> _ScalarNumpy: ...
+@overload
+def take(
+ a: ArrayLike,
+ indices: int,
+ axis: Optional[int] = ...,
+ out: Optional[ndarray] = ...,
+ mode: _Mode = ...,
+) -> _ScalarNumpy: ...
+@overload
+def take(
+ a: ArrayLike,
+ indices: _ArrayLikeIntOrBool,
+ axis: Optional[int] = ...,
+ out: Optional[ndarray] = ...,
+ mode: _Mode = ...,
+) -> Union[_ScalarNumpy, ndarray]: ...
+def reshape(a: ArrayLike, newshape: _ShapeLike, order: _Order = ...) -> ndarray: ...
+@overload
+def choose(
+ a: _ScalarIntOrBool,
+ choices: ArrayLike,
+ out: Optional[ndarray] = ...,
+ mode: _Mode = ...,
+) -> _ScalarIntOrBool: ...
+@overload
+def choose(
+ a: _IntOrBool, choices: ArrayLike, out: Optional[ndarray] = ..., mode: _Mode = ...
+) -> Union[integer, bool_]: ...
+@overload
+def choose(
+ a: _ArrayLikeIntOrBool,
+ choices: ArrayLike,
+ out: Optional[ndarray] = ...,
+ mode: _Mode = ...,
+) -> ndarray: ...
+def repeat(
+ a: ArrayLike, repeats: _ArrayLikeIntOrBool, axis: Optional[int] = ...
+) -> ndarray: ...
+def put(
+ a: ndarray, ind: _ArrayLikeIntOrBool, v: ArrayLike, mode: _Mode = ...
+) -> None: ...
+def swapaxes(a: ArrayLike, axis1: int, axis2: int) -> ndarray: ...
+def transpose(
+ a: ArrayLike, axes: Union[None, Sequence[int], ndarray] = ...
+) -> ndarray: ...
+def partition(
+ a: ArrayLike,
+ kth: _ArrayLikeIntOrBool,
+ axis: Optional[int] = ...,
+ kind: _PartitionKind = ...,
+ order: Union[None, str, Sequence[str]] = ...,
+) -> ndarray: ...
+@overload
+def argpartition(
+ a: generic,
+ kth: _ArrayLikeIntOrBool,
+ axis: Optional[int] = ...,
+ kind: _PartitionKind = ...,
+ order: Union[None, str, Sequence[str]] = ...,
+) -> integer: ...
+@overload
+def argpartition(
+ a: _ScalarBuiltin,
+ kth: _ArrayLikeIntOrBool,
+ axis: Optional[int] = ...,
+ kind: _PartitionKind = ...,
+ order: Union[None, str, Sequence[str]] = ...,
+) -> ndarray: ...
+@overload
+def argpartition(
+ a: ArrayLike,
+ kth: _ArrayLikeIntOrBool,
+ axis: Optional[int] = ...,
+ kind: _PartitionKind = ...,
+ order: Union[None, str, Sequence[str]] = ...,
+) -> ndarray: ...
+def sort(
+ a: ArrayLike,
+ axis: Optional[int] = ...,
+ kind: Optional[_SortKind] = ...,
+ order: Union[None, str, Sequence[str]] = ...,
+) -> ndarray: ...
+def argsort(
+ a: ArrayLike,
+ axis: Optional[int] = ...,
+ kind: Optional[_SortKind] = ...,
+ order: Union[None, str, Sequence[str]] = ...,
+) -> ndarray: ...
+@overload
+def argmax(a: ArrayLike, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ...
+@overload
+def argmax(
+ a: ArrayLike, axis: int = ..., out: Optional[ndarray] = ...
+) -> Union[integer, ndarray]: ...
+@overload
+def argmin(a: ArrayLike, axis: None = ..., out: Optional[ndarray] = ...) -> integer: ...
+@overload
+def argmin(
+ a: ArrayLike, axis: int = ..., out: Optional[ndarray] = ...
+) -> Union[integer, ndarray]: ...
+@overload
+def searchsorted(
+ a: ArrayLike,
+ v: _Scalar,
+ side: _Side = ...,
+ sorter: Optional[_ArrayLikeIntOrBool] = ..., # 1D int array
+) -> integer: ...
+@overload
+def searchsorted(
+ a: ArrayLike,
+ v: ArrayLike,
+ side: _Side = ...,
+ sorter: Optional[_ArrayLikeIntOrBool] = ..., # 1D int array
+) -> ndarray: ...
+def resize(a: ArrayLike, new_shape: _ShapeLike) -> ndarray: ...
+@overload
+def squeeze(a: _ScalarGeneric, axis: Optional[_ShapeLike] = ...) -> _ScalarGeneric: ...
+@overload
+def squeeze(a: ArrayLike, axis: Optional[_ShapeLike] = ...) -> ndarray: ...
+def diagonal(
+ a: ArrayLike, offset: int = ..., axis1: int = ..., axis2: int = ... # >= 2D array
+) -> ndarray: ...
+def trace(
+ a: ArrayLike, # >= 2D array
+ offset: int = ...,
+ axis1: int = ...,
+ axis2: int = ...,
+ dtype: DtypeLike = ...,
+ out: Optional[ndarray] = ...,
+) -> Union[number, ndarray]: ...
+def ravel(a: ArrayLike, order: _Order = ...) -> ndarray: ...
+def nonzero(a: ArrayLike) -> Tuple[ndarray, ...]: ...
+def shape(a: ArrayLike) -> _Shape: ...
+def compress(
+ condition: ArrayLike, # 1D bool array
+ a: ArrayLike,
+ axis: Optional[int] = ...,
+ out: Optional[ndarray] = ...,
+) -> ndarray: ...
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py
index 20ad39b05..d0ed3d381 100644
--- a/numpy/core/_add_newdocs.py
+++ b/numpy/core/_add_newdocs.py
@@ -1525,7 +1525,7 @@ add_newdoc('numpy.core.multiarray', 'c_einsum',
Controls the memory layout of the output. 'C' means it should
be C contiguous. 'F' means it should be Fortran contiguous,
'A' means it should be 'F' if the inputs are all 'F', 'C' otherwise.
- 'K' means it should be as close to the layout as the inputs as
+ 'K' means it should be as close to the layout of the inputs as
is possible, including arbitrarily permuted axes.
Default is 'K'.
casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
@@ -3243,15 +3243,13 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('newbyteorder',
below. `new_order` codes can be any of:
* 'S' - swap dtype from current to opposite endian
- * {'<', 'L'} - little endian
- * {'>', 'B'} - big endian
- * {'=', 'N'} - native order
+ * {'<', 'little'} - little endian
+ * {'>', 'big'} - big endian
+ * '=' - native order, equivalent to `sys.byteorder`
* {'|', 'I'} - ignore (no change to byte order)
The default value ('S') results in swapping the current
- byte order. The code does a case-insensitive check on the first
- letter of `new_order` for the alternatives above. For example,
- any of 'B' or 'b' or 'biggish' are valid to specify big-endian.
+ byte order.
Returns
@@ -3938,18 +3936,17 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tobytes', """
Construct Python bytes containing the raw data bytes in the array.
Constructs Python bytes showing a copy of the raw contents of
- data memory. The bytes object can be produced in either 'C' or 'Fortran',
- or 'Any' order (the default is 'C'-order). 'Any' order means C-order
- unless the F_CONTIGUOUS flag in the array is set, in which case it
- means 'Fortran' order.
+ data memory. The bytes object is produced in C-order by default.
+ This behavior is controlled by the ``order`` parameter.
.. versionadded:: 1.9.0
Parameters
----------
- order : {'C', 'F', None}, optional
- Order of the data for multidimensional arrays:
- C, Fortran, or the same as for the original array.
+ order : {'C', 'F', 'A'}, optional
+ Controls the memory layout of the bytes object. 'C' means C-order,
+ 'F' means F-order, 'A' (short for *Any*) means 'F' if `a` is
+ Fortran contiguous, 'C' otherwise. Default is 'C'.
Returns
-------
@@ -5144,7 +5141,7 @@ add_newdoc('numpy.core', 'ufunc', ('at',
add_newdoc('numpy.core.multiarray', 'dtype',
"""
- dtype(obj, align=False, copy=False)
+ dtype(dtype, align=False, copy=False)
Create a data type object.
@@ -5154,7 +5151,7 @@ add_newdoc('numpy.core.multiarray', 'dtype',
Parameters
----------
- obj
+ dtype
Object to be converted to a data type object.
align : bool, optional
Add padding to the fields to match what a C compiler would output
@@ -5666,15 +5663,11 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('newbyteorder',
byte order. `new_order` codes can be any of:
* 'S' - swap dtype from current to opposite endian
- * {'<', 'L'} - little endian
- * {'>', 'B'} - big endian
- * {'=', 'N'} - native order
+ * {'<', 'little'} - little endian
+ * {'>', 'big'} - big endian
+ * '=' - native order
* {'|', 'I'} - ignore (no change to byte order)
- The code does a case-insensitive check on the first letter of
- `new_order` for these alternatives. For example, any of '>'
- or 'B' or 'b' or 'brian' are valid to specify big-endian.
-
Returns
-------
new_dtype : dtype
@@ -6041,9 +6034,9 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('newbyteorder',
The `new_order` code can be any from the following:
* 'S' - swap dtype from current to opposite endian
- * {'<', 'L'} - little endian
- * {'>', 'B'} - big endian
- * {'=', 'N'} - native order
+ * {'<', 'little'} - little endian
+ * {'>', 'big'} - big endian
+ * '=' - native order
* {'|', 'I'} - ignore (no change to byte order)
Parameters
@@ -6051,9 +6044,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('newbyteorder',
new_order : str, optional
Byte order to force; a value from the byte order specifications
above. The default value ('S') results in swapping the current
- byte order. The code does a case-insensitive check on the first
- letter of `new_order` for the alternatives above. For example,
- any of 'B' or 'b' or 'biggish' are valid to specify big-endian.
+ byte order.
Returns
diff --git a/numpy/core/_dtype.py b/numpy/core/_dtype.py
index 76d0b8149..50aeeb5bc 100644
--- a/numpy/core/_dtype.py
+++ b/numpy/core/_dtype.py
@@ -160,13 +160,13 @@ def _scalar_str(dtype, short):
def _byte_order_str(dtype):
""" Normalize byteorder to '<' or '>' """
# hack to obtain the native and swapped byte order characters
- swapped = np.dtype(int).newbyteorder('s')
- native = swapped.newbyteorder('s')
+ swapped = np.dtype(int).newbyteorder('S')
+ native = swapped.newbyteorder('S')
byteorder = dtype.byteorder
if byteorder == '=':
return native.byteorder
- if byteorder == 's':
+ if byteorder == 'S':
# TODO: this path can never be reached
return swapped.byteorder
elif byteorder == '|':
diff --git a/numpy/core/_internal.pyi b/numpy/core/_internal.pyi
new file mode 100644
index 000000000..1b3889e51
--- /dev/null
+++ b/numpy/core/_internal.pyi
@@ -0,0 +1,18 @@
+from typing import Any
+
+# TODO: add better annotations when ctypes is stubbed out
+
+class _ctypes:
+ @property
+ def data(self) -> int: ...
+ @property
+ def shape(self) -> Any: ...
+ @property
+ def strides(self) -> Any: ...
+ def data_as(self, obj: Any) -> Any: ...
+ def shape_as(self, obj: Any) -> Any: ...
+ def strides_as(self, obj: Any) -> Any: ...
+ def get_data(self) -> int: ...
+ def get_shape(self) -> Any: ...
+ def get_strides(self) -> Any: ...
+ def get_as_parameter(self) -> Any: ...
diff --git a/numpy/core/_type_aliases.py b/numpy/core/_type_aliases.py
index c26431443..de90fd818 100644
--- a/numpy/core/_type_aliases.py
+++ b/numpy/core/_type_aliases.py
@@ -11,40 +11,19 @@ and sometimes other mappings too.
.. data:: sctypeDict
Similar to `allTypes`, but maps a broader set of aliases to their types.
-.. data:: sctypeNA
- NumArray-compatible names for the scalar types. Contains not only
- ``name: type`` mappings, but ``char: name`` mappings too.
-
- .. deprecated:: 1.16
-
.. data:: sctypes
A dictionary keyed by a "type group" string, providing a list of types
under that group.
"""
-import warnings
from numpy.compat import unicode
-from numpy._globals import VisibleDeprecationWarning
-from numpy.core._string_helpers import english_lower, english_capitalize
+from numpy.core._string_helpers import english_lower
from numpy.core.multiarray import typeinfo, dtype
from numpy.core._dtype import _kind_name
sctypeDict = {} # Contains all leaf-node scalar types with aliases
-class TypeNADict(dict):
- def __getitem__(self, key):
- # 2018-06-24, 1.16
- warnings.warn('sctypeNA and typeNA will be removed in v1.18 '
- 'of numpy', VisibleDeprecationWarning, stacklevel=2)
- return dict.__getitem__(self, key)
- def get(self, key, default=None):
- # 2018-06-24, 1.16
- warnings.warn('sctypeNA and typeNA will be removed in v1.18 '
- 'of numpy', VisibleDeprecationWarning, stacklevel=2)
- return dict.get(self, key, default)
-
-sctypeNA = TypeNADict() # Contails all leaf-node types -> numarray type equivalences
allTypes = {} # Collect the types we will add to the module
@@ -127,27 +106,24 @@ def _add_aliases():
if name in ('longdouble', 'clongdouble') and myname in allTypes:
continue
- base_capitalize = english_capitalize(base)
- if base == 'complex':
- na_name = '%s%d' % (base_capitalize, bit//2)
- elif base == 'bool':
- na_name = base_capitalize
- else:
- na_name = "%s%d" % (base_capitalize, bit)
-
allTypes[myname] = info.type
# add mapping for both the bit name and the numarray name
sctypeDict[myname] = info.type
- sctypeDict[na_name] = info.type
# add forward, reverse, and string mapping to numarray
- sctypeNA[na_name] = info.type
- sctypeNA[info.type] = na_name
- sctypeNA[info.char] = na_name
-
sctypeDict[char] = info.type
- sctypeNA[char] = na_name
+
+ # Add deprecated numeric-style type aliases manually, at some point
+ # we may want to deprecate the lower case "bytes0" version as well.
+ for name in ["Bytes0", "Datetime64", "Str0", "Uint32", "Uint64"]:
+ if english_lower(name) not in allTypes:
+ # Only one of Uint32 or Uint64, aliases of `np.uintp`, was (and is) defined, note that this
+ # is not UInt32/UInt64 (capital i), which is removed.
+ continue
+ allTypes[name] = allTypes[english_lower(name)]
+ sctypeDict[name] = sctypeDict[english_lower(name)]
+
_add_aliases()
def _add_integer_aliases():
@@ -157,20 +133,15 @@ def _add_integer_aliases():
u_info = _concrete_typeinfo[u_ctype]
bits = i_info.bits # same for both
- for info, charname, intname, Intname in [
- (i_info,'i%d' % (bits//8,), 'int%d' % bits, 'Int%d' % bits),
- (u_info,'u%d' % (bits//8,), 'uint%d' % bits, 'UInt%d' % bits)]:
+ for info, charname, intname in [
+ (i_info,'i%d' % (bits//8,), 'int%d' % bits),
+ (u_info,'u%d' % (bits//8,), 'uint%d' % bits)]:
if bits not in seen_bits:
# sometimes two different types have the same number of bits
# if so, the one iterated over first takes precedence
allTypes[intname] = info.type
sctypeDict[intname] = info.type
- sctypeDict[Intname] = info.type
sctypeDict[charname] = info.type
- sctypeNA[Intname] = info.type
- sctypeNA[charname] = info.type
- sctypeNA[info.type] = Intname
- sctypeNA[info.char] = Intname
seen_bits.add(bits)
diff --git a/numpy/core/einsumfunc.py b/numpy/core/einsumfunc.py
index c46ae173d..f65f4015c 100644
--- a/numpy/core/einsumfunc.py
+++ b/numpy/core/einsumfunc.py
@@ -1358,11 +1358,18 @@ def einsum(*operands, out=None, optimize=False, **kwargs):
raise TypeError("Did not understand the following kwargs: %s"
% unknown_kwargs)
-
# Build the contraction list and operand
operands, contraction_list = einsum_path(*operands, optimize=optimize,
einsum_call=True)
+ # Handle order kwarg for output array, c_einsum allows mixed case
+ output_order = kwargs.pop('order', 'K')
+ if output_order.upper() == 'A':
+ if all(arr.flags.f_contiguous for arr in operands):
+ output_order = 'F'
+ else:
+ output_order = 'C'
+
# Start contraction loop
for num, contraction in enumerate(contraction_list):
inds, idx_rm, einsum_str, remaining, blas = contraction
@@ -1412,4 +1419,4 @@ def einsum(*operands, out=None, optimize=False, **kwargs):
if specified_out:
return out
else:
- return operands[0]
+ return asanyarray(operands[0], order=output_order)
diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py
index 9e46f0ea5..f57e95742 100644
--- a/numpy/core/function_base.py
+++ b/numpy/core/function_base.py
@@ -52,8 +52,10 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
If True, return (`samples`, `step`), where `step` is the spacing
between samples.
dtype : dtype, optional
- The type of the output array. If `dtype` is not given, infer the data
- type from the other input arguments.
+ The type of the output array. If `dtype` is not given, the data type
+ is inferred from `start` and `stop`. The inferred dtype will never be
+ an integer; `float` is chosen even if the arguments would produce an
+ array of integers.
.. versionadded:: 1.9.0
@@ -202,8 +204,10 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,
``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform.
Default is 10.0.
dtype : dtype
- The type of the output array. If `dtype` is not given, infer the data
- type from the other input arguments.
+ The type of the output array. If `dtype` is not given, the data type
+ is inferred from `start` and `stop`. The inferred type will never be
+ an integer; `float` is chosen even if the arguments would produce an
+ array of integers.
axis : int, optional
The axis in the result to store the samples. Relevant only if start
or stop are array-like. By default (0), the samples will be along a
@@ -297,8 +301,10 @@ def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
If true, `stop` is the last sample. Otherwise, it is not included.
Default is True.
dtype : dtype
- The type of the output array. If `dtype` is not given, infer the data
- type from the other input arguments.
+ The type of the output array. If `dtype` is not given, the data type
+ is inferred from `start` and `stop`. The inferred dtype will never be
+ an integer; `float` is chosen even if the arguments would produce an
+ array of integers.
axis : int, optional
The axis in the result to store the samples. Relevant only if start
or stop are array-like. By default (0), the samples will be along a
@@ -408,8 +414,18 @@ def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
log_start = _nx.log10(start)
log_stop = _nx.log10(stop)
- result = out_sign * logspace(log_start, log_stop, num=num,
- endpoint=endpoint, base=10.0, dtype=dtype)
+ result = logspace(log_start, log_stop, num=num,
+ endpoint=endpoint, base=10.0, dtype=dtype)
+
+ # Make sure the endpoints match the start and stop arguments. This is
+ # necessary because np.exp(np.log(x)) is not necessarily equal to x.
+ if num > 0:
+ result[0] = start
+ if num > 1 and endpoint:
+ result[-1] = stop
+
+ result = out_sign * result
+
if axis != 0:
result = _nx.moveaxis(result, 0, axis)
diff --git a/numpy/core/include/numpy/npy_3kcompat.h b/numpy/core/include/numpy/npy_3kcompat.h
index 798da6957..7e6b01924 100644
--- a/numpy/core/include/numpy/npy_3kcompat.h
+++ b/numpy/core/include/numpy/npy_3kcompat.h
@@ -62,9 +62,9 @@ static NPY_INLINE int PyInt_Check(PyObject *op) {
#if PY_VERSION_HEX < 0x030900a4
/* Introduced in https://github.com/python/cpython/commit/d2ec81a8c99796b51fb8c49b77a7fe369863226f */
- #define Py_SET_TYPE(obj, typ) (Py_TYPE(obj) = typ)
+ #define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0)
/* Introduced in https://github.com/python/cpython/commit/b10dc3e7a11fcdb97e285882eba6da92594f90f9 */
- #define Py_SET_SIZE(obj, size) (Py_SIZE(obj) = size)
+ #define Py_SET_SIZE(obj, size) ((Py_SIZE(obj) = (size)), (void)0)
#endif
diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py
index aac741612..2a015f48f 100644
--- a/numpy/core/numerictypes.py
+++ b/numpy/core/numerictypes.py
@@ -91,7 +91,7 @@ from numpy.core.multiarray import (
from numpy.core.overrides import set_module
# we add more at the bottom
-__all__ = ['sctypeDict', 'sctypeNA', 'typeDict', 'typeNA', 'sctypes',
+__all__ = ['sctypeDict', 'typeDict', 'sctypes',
'ScalarType', 'obj2sctype', 'cast', 'nbytes', 'sctype2char',
'maximum_sctype', 'issctype', 'typecodes', 'find_common_type',
'issubdtype', 'datetime_data', 'datetime_as_string',
@@ -106,7 +106,6 @@ from ._string_helpers import (
from ._type_aliases import (
sctypeDict,
- sctypeNA,
allTypes,
bitname,
sctypes,
@@ -512,7 +511,6 @@ typecodes = {'Character':'c',
# backwards compatibility --- deprecated name
typeDict = sctypeDict
-typeNA = sctypeNA
# b -> boolean
# u -> unsigned integer
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 16bac4272..5351b30bf 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -967,6 +967,7 @@ def configuration(parent_package='',top_path=None):
config.add_subpackage('tests')
config.add_data_dir('tests/data')
config.add_data_dir('tests/examples')
+ config.add_data_files('*.pyi')
config.make_svn_version_py()
diff --git a/numpy/core/src/common/npy_cpu_features.c.src b/numpy/core/src/common/npy_cpu_features.c.src
index bd4743905..d35199760 100644
--- a/numpy/core/src/common/npy_cpu_features.c.src
+++ b/numpy/core/src/common/npy_cpu_features.c.src
@@ -283,28 +283,7 @@ npy__cpu_init_features_arm8(void)
* so we play it safe
*/
#include <stdio.h>
-#include <fcntl.h>
-
-#define NPY__HWCAP 16
-#define NPY__HWCAP2 26
-
-// arch/arm/include/uapi/asm/hwcap.h
-#define NPY__HWCAP_HALF (1 << 1)
-#define NPY__HWCAP_NEON (1 << 12)
-#define NPY__HWCAP_VFPv3 (1 << 13)
-#define NPY__HWCAP_VFPv4 (1 << 16)
-#define NPY__HWCAP2_AES (1 << 0)
-#define NPY__HWCAP2_PMULL (1 << 1)
-#define NPY__HWCAP2_SHA1 (1 << 2)
-#define NPY__HWCAP2_SHA2 (1 << 3)
-#define NPY__HWCAP2_CRC32 (1 << 4)
-// arch/arm64/include/uapi/asm/hwcap.h
-#define NPY__HWCAP_FP (1 << 0)
-#define NPY__HWCAP_ASIMD (1 << 1)
-#define NPY__HWCAP_FPHP (1 << 9)
-#define NPY__HWCAP_ASIMDHP (1 << 10)
-#define NPY__HWCAP_ASIMDDP (1 << 20)
-#define NPY__HWCAP_ASIMDFHM (1 << 23)
+#include "npy_cpuinfo_parser.h"
__attribute__((weak)) unsigned long getauxval(unsigned long); // linker should handle it
static int
@@ -339,10 +318,12 @@ npy__cpu_init_features_linux(void)
}
if (hwcap == 0 && hwcap2 == 0) {
/*
- * FIXME: failback to compiler definitions,
- * BTW we can parse /proc/cpuinfo for badly patched kernels
+ * try parsing with /proc/cpuinfo, if sandboxed
+ * failback to compiler definitions
*/
- return 0;
+ if(!get_feature_from_proc_cpuinfo(&hwcap, &hwcap2)) {
+ return 0;
+ }
}
#ifdef __arm__
// Detect Arm8 (aarch32 state)
@@ -367,9 +348,10 @@ npy__cpu_init_features_linux(void)
npy__cpu_init_features_arm8();
} else {
npy__cpu_have[NPY_CPU_FEATURE_NEON] = (hwcap & NPY__HWCAP_NEON) != 0;
- npy__cpu_have[NPY_CPU_FEATURE_NEON_FP16] = (hwcap & (NPY__HWCAP_NEON | NPY__HWCAP_VFPv3 |
- NPY__HWCAP_HALF)) != 0;
- npy__cpu_have[NPY_CPU_FEATURE_NEON_VFPV4] = (hwcap & (NPY__HWCAP_NEON | NPY__HWCAP_VFPv4)) != 0;
+ if (npy__cpu_have[NPY_CPU_FEATURE_NEON]) {
+ npy__cpu_have[NPY_CPU_FEATURE_NEON_FP16] = (hwcap & NPY__HWCAP_HALF) != 0;
+ npy__cpu_have[NPY_CPU_FEATURE_NEON_VFPV4] = (hwcap & NPY__HWCAP_VFPv4) != 0;
+ }
}
return 1;
}
diff --git a/numpy/core/src/common/npy_cpuinfo_parser.h b/numpy/core/src/common/npy_cpuinfo_parser.h
new file mode 100644
index 000000000..4c00c847b
--- /dev/null
+++ b/numpy/core/src/common/npy_cpuinfo_parser.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef __NPY_CPUINFO_PARSER_H__
+#define __NPY_CPUINFO_PARSER_H__
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+
+#define NPY__HWCAP 16
+#define NPY__HWCAP2 26
+
+// arch/arm/include/uapi/asm/hwcap.h
+#define NPY__HWCAP_HALF (1 << 1)
+#define NPY__HWCAP_NEON (1 << 12)
+#define NPY__HWCAP_VFPv3 (1 << 13)
+#define NPY__HWCAP_VFPv4 (1 << 16)
+#define NPY__HWCAP2_AES (1 << 0)
+#define NPY__HWCAP2_PMULL (1 << 1)
+#define NPY__HWCAP2_SHA1 (1 << 2)
+#define NPY__HWCAP2_SHA2 (1 << 3)
+#define NPY__HWCAP2_CRC32 (1 << 4)
+// arch/arm64/include/uapi/asm/hwcap.h
+#define NPY__HWCAP_FP (1 << 0)
+#define NPY__HWCAP_ASIMD (1 << 1)
+#define NPY__HWCAP_FPHP (1 << 9)
+#define NPY__HWCAP_ASIMDHP (1 << 10)
+#define NPY__HWCAP_ASIMDDP (1 << 20)
+#define NPY__HWCAP_ASIMDFHM (1 << 23)
+/*
+ * Get the size of a file by reading it until the end. This is needed
+ * because files under /proc do not always return a valid size when
+ * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed.
+ */
+static int
+get_file_size(const char* pathname)
+{
+ int fd, result = 0;
+ char buffer[256];
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ return -1;
+ }
+
+ for (;;) {
+ int ret = read(fd, buffer, sizeof buffer);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ break;
+ }
+ if (ret == 0) {
+ break;
+ }
+ result += ret;
+ }
+ close(fd);
+ return result;
+}
+
+/*
+ * Read the content of /proc/cpuinfo into a user-provided buffer.
+ * Return the length of the data, or -1 on error. Does *not*
+ * zero-terminate the content. Will not read more
+ * than 'buffsize' bytes.
+ */
+static int
+read_file(const char* pathname, char* buffer, size_t buffsize)
+{
+ int fd, count;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ return -1;
+ }
+ count = 0;
+ while (count < (int)buffsize) {
+ int ret = read(fd, buffer + count, buffsize - count);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ if (count == 0) {
+ count = -1;
+ }
+ break;
+ }
+ if (ret == 0) {
+ break;
+ }
+ count += ret;
+ }
+ close(fd);
+ return count;
+}
+
+/*
+ * Extract the content of a the first occurence of a given field in
+ * the content of /proc/cpuinfo and return it as a heap-allocated
+ * string that must be freed by the caller.
+ *
+ * Return NULL if not found
+ */
+static char*
+extract_cpuinfo_field(const char* buffer, int buflen, const char* field)
+{
+ int fieldlen = strlen(field);
+ const char* bufend = buffer + buflen;
+ char* result = NULL;
+ int len;
+ const char *p, *q;
+
+ /* Look for first field occurence, and ensures it starts the line. */
+ p = buffer;
+ for (;;) {
+ p = memmem(p, bufend-p, field, fieldlen);
+ if (p == NULL) {
+ goto EXIT;
+ }
+
+ if (p == buffer || p[-1] == '\n') {
+ break;
+ }
+
+ p += fieldlen;
+ }
+
+ /* Skip to the first column followed by a space */
+ p += fieldlen;
+ p = memchr(p, ':', bufend-p);
+ if (p == NULL || p[1] != ' ') {
+ goto EXIT;
+ }
+
+ /* Find the end of the line */
+ p += 2;
+ q = memchr(p, '\n', bufend-p);
+ if (q == NULL) {
+ q = bufend;
+ }
+
+ /* Copy the line into a heap-allocated buffer */
+ len = q - p;
+ result = malloc(len + 1);
+ if (result == NULL) {
+ goto EXIT;
+ }
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+EXIT:
+ return result;
+}
+
+/*
+ * Checks that a space-separated list of items contains one given 'item'.
+ * Returns 1 if found, 0 otherwise.
+ */
+static int
+has_list_item(const char* list, const char* item)
+{
+ const char* p = list;
+ int itemlen = strlen(item);
+
+ if (list == NULL) {
+ return 0;
+ }
+
+ while (*p) {
+ const char* q;
+
+ /* skip spaces */
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+
+ /* find end of current list item */
+ q = p;
+ while (*q && *q != ' ' && *q != '\t') {
+ q++;
+ }
+
+ if (itemlen == q-p && !memcmp(p, item, itemlen)) {
+ return 1;
+ }
+
+ /* skip to next item */
+ p = q;
+ }
+ return 0;
+}
+
+static void setHwcap(char* cpuFeatures, unsigned long* hwcap) {
+ *hwcap |= has_list_item(cpuFeatures, "neon") ? NPY__HWCAP_NEON : 0;
+ *hwcap |= has_list_item(cpuFeatures, "half") ? NPY__HWCAP_HALF : 0;
+ *hwcap |= has_list_item(cpuFeatures, "vfpv3") ? NPY__HWCAP_VFPv3 : 0;
+ *hwcap |= has_list_item(cpuFeatures, "vfpv4") ? NPY__HWCAP_VFPv4 : 0;
+
+ *hwcap |= has_list_item(cpuFeatures, "asimd") ? NPY__HWCAP_ASIMD : 0;
+ *hwcap |= has_list_item(cpuFeatures, "fp") ? NPY__HWCAP_FP : 0;
+ *hwcap |= has_list_item(cpuFeatures, "fphp") ? NPY__HWCAP_FPHP : 0;
+ *hwcap |= has_list_item(cpuFeatures, "asimdhp") ? NPY__HWCAP_ASIMDHP : 0;
+ *hwcap |= has_list_item(cpuFeatures, "asimddp") ? NPY__HWCAP_ASIMDDP : 0;
+ *hwcap |= has_list_item(cpuFeatures, "asimdfhm") ? NPY__HWCAP_ASIMDFHM : 0;
+}
+
+static int
+get_feature_from_proc_cpuinfo(unsigned long *hwcap, unsigned long *hwcap2) {
+ char* cpuinfo = NULL;
+ int cpuinfo_len;
+ cpuinfo_len = get_file_size("/proc/cpuinfo");
+ if (cpuinfo_len < 0) {
+ return 0;
+ }
+ cpuinfo = malloc(cpuinfo_len);
+ if (cpuinfo == NULL) {
+ return 0;
+ }
+ cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, cpuinfo_len);
+ char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
+ if(cpuFeatures == NULL) {
+ return 0;
+ }
+ setHwcap(cpuFeatures, hwcap);
+ *hwcap2 |= *hwcap;
+ *hwcap2 |= has_list_item(cpuFeatures, "aes") ? NPY__HWCAP2_AES : 0;
+ *hwcap2 |= has_list_item(cpuFeatures, "pmull") ? NPY__HWCAP2_PMULL : 0;
+ *hwcap2 |= has_list_item(cpuFeatures, "sha1") ? NPY__HWCAP2_SHA1 : 0;
+ *hwcap2 |= has_list_item(cpuFeatures, "sha2") ? NPY__HWCAP2_SHA2 : 0;
+ *hwcap2 |= has_list_item(cpuFeatures, "crc32") ? NPY__HWCAP2_CRC32 : 0;
+ return 1;
+}
+#endif
diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c
index 0e49b0d63..e41fdc8f1 100644
--- a/numpy/core/src/multiarray/conversion_utils.c
+++ b/numpy/core/src/multiarray/conversion_utils.c
@@ -371,8 +371,11 @@ string_converter_helper(
int ret = str_func(str, length, out);
Py_DECREF(str_object);
if (ret < 0) {
+ /* str_func returns -1 without an exception if the value is wrong */
+ if (!PyErr_Occurred()) {
PyErr_Format(PyExc_ValueError,
"%s %s (got %R)", name, message, object);
+ }
return NPY_FAIL;
}
return NPY_SUCCEED;
@@ -385,8 +388,8 @@ static int byteorder_parser(char const *str, Py_ssize_t length, void *data)
if (length < 1) {
return -1;
}
- else if (str[0] == NPY_BIG || str[0] == NPY_LITTLE
- || str[0] == NPY_NATIVE || str[0] == NPY_IGNORE) {
+ else if (str[0] == NPY_BIG || str[0] == NPY_LITTLE ||
+ str[0] == NPY_NATIVE || str[0] == NPY_IGNORE) {
*endian = str[0];
return 0;
}
@@ -508,21 +511,36 @@ PyArray_SelectkindConverter(PyObject *obj, NPY_SELECTKIND *selectkind)
static int searchside_parser(char const *str, Py_ssize_t length, void *data)
{
NPY_SEARCHSIDE *side = (NPY_SEARCHSIDE *)data;
+ int is_exact = 0;
if (length < 1) {
return -1;
}
else if (str[0] == 'l' || str[0] == 'L') {
*side = NPY_SEARCHLEFT;
- return 0;
+ is_exact = (length == 4 && strcmp(str, "left") == 0);
}
else if (str[0] == 'r' || str[0] == 'R') {
*side = NPY_SEARCHRIGHT;
- return 0;
+ is_exact = (length == 5 && strcmp(str, "right") == 0);
}
else {
return -1;
}
+
+ /* Filters out the case sensitive/non-exact
+ * match inputs and other inputs and outputs DeprecationWarning
+ */
+ if (!is_exact) {
+ /* NumPy 1.20, 2020-05-19 */
+ if (DEPRECATE("inexact matches and case insensitive matches "
+ "for search side are deprecated, please use "
+ "one of 'left' or 'right' instead.") < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
}
/*NUMPY_API
@@ -581,24 +599,40 @@ PyArray_OrderConverter(PyObject *object, NPY_ORDER *val)
static int clipmode_parser(char const *str, Py_ssize_t length, void *data)
{
NPY_CLIPMODE *val = (NPY_CLIPMODE *)data;
+ int is_exact = 0;
+
if (length < 1) {
return -1;
}
if (str[0] == 'C' || str[0] == 'c') {
*val = NPY_CLIP;
- return 0;
+ is_exact = (length == 4 && strcmp(str, "clip") == 0);
}
else if (str[0] == 'W' || str[0] == 'w') {
*val = NPY_WRAP;
- return 0;
+ is_exact = (length == 4 && strcmp(str, "wrap") == 0);
}
else if (str[0] == 'R' || str[0] == 'r') {
*val = NPY_RAISE;
- return 0;
+ is_exact = (length == 5 && strcmp(str, "raise") == 0);
}
else {
return -1;
}
+
+ /* Filters out the case sensitive/non-exact
+ * match inputs and other inputs and outputs DeprecationWarning
+ */
+ if (!is_exact) {
+ /* Numpy 1.20, 2020-05-19 */
+ if (DEPRECATE("inexact matches and case insensitive matches "
+ "for clip mode are deprecated, please use "
+ "one of 'clip', 'raise', or 'wrap' instead.") < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
}
/*NUMPY_API
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 8d884bc00..4ebd5640d 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1678,14 +1678,14 @@ _convert_from_str(PyObject *obj, int align)
}
/* Check for a deprecated Numeric-style typecode */
- char *dep_tps[] = {"Bool", "Complex", "Float", "Int",
- "Object0", "String0", "Timedelta64",
- "Unicode0", "UInt", "Void0"};
+ /* `Uint` has deliberately weird uppercasing */
+ char *dep_tps[] = {"Bytes", "Datetime64", "Str", "Uint"};
int ndep_tps = sizeof(dep_tps) / sizeof(dep_tps[0]);
for (int i = 0; i < ndep_tps; ++i) {
char *dep_tp = dep_tps[i];
if (strncmp(type, dep_tp, strlen(dep_tp)) == 0) {
+ /* Deprecated 2020-06-09, NumPy 1.20 */
if (DEPRECATE("Numeric-style type codes are "
"deprecated and will result in "
"an error in the future.") < 0) {
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c
index 7aefbfc38..f73cb48d9 100644
--- a/numpy/core/src/multiarray/mapping.c
+++ b/numpy/core/src/multiarray/mapping.c
@@ -2480,8 +2480,6 @@ PyArray_MapIterCheckIndices(PyArrayMapIterObject *mit)
int i;
NPY_BEGIN_THREADS_DEF;
- intp_type = PyArray_DescrFromType(NPY_INTP);
-
if (NpyIter_GetIterSize(mit->outer) == 0) {
/*
* When the outer iteration is empty, the indices broadcast to an
@@ -2493,6 +2491,8 @@ PyArray_MapIterCheckIndices(PyArrayMapIterObject *mit)
return 0;
}
+ intp_type = PyArray_DescrFromType(NPY_INTP);
+
NPY_BEGIN_THREADS;
for (i=0; i < mit->numiter; i++) {
diff --git a/numpy/core/src/umath/simd.inc.src b/numpy/core/src/umath/simd.inc.src
index 48e89915c..e6414e29e 100644
--- a/numpy/core/src/umath/simd.inc.src
+++ b/numpy/core/src/umath/simd.inc.src
@@ -2698,17 +2698,17 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
/* process elements using glibc for large elements */
if (my_trig_op == npy_compute_cos) {
- for (int ii = 0; iglibc_mask != 0; ii++) {
+ for (int ii = 0, jj = 0; iglibc_mask != 0; ii++, jj += stride) {
if (iglibc_mask & 0x01) {
- op[ii] = npy_cosf(ip[ii]);
+ op[ii] = npy_cosf(ip[jj]);
}
iglibc_mask = iglibc_mask >> 1;
}
}
else {
- for (int ii = 0; iglibc_mask != 0; ii++) {
+ for (int ii = 0, jj = 0; iglibc_mask != 0; ii++, jj += stride) {
if (iglibc_mask & 0x01) {
- op[ii] = npy_sinf(ip[ii]);
+ op[ii] = npy_sinf(ip[jj]);
}
iglibc_mask = iglibc_mask >> 1;
}
diff --git a/numpy/core/tests/test_conversion_utils.py b/numpy/core/tests/test_conversion_utils.py
index e96113d09..d8849ee29 100644
--- a/numpy/core/tests/test_conversion_utils.py
+++ b/numpy/core/tests/test_conversion_utils.py
@@ -7,19 +7,31 @@ import pytest
import numpy as np
import numpy.core._multiarray_tests as mt
+from numpy.testing import assert_warns
class StringConverterTestCase:
allow_bytes = True
case_insensitive = True
exact_match = False
+ warn = True
def _check_value_error(self, val):
pattern = r'\(got {}\)'.format(re.escape(repr(val)))
with pytest.raises(ValueError, match=pattern) as exc:
self.conv(val)
+ def _check_conv_assert_warn(self, val, expected):
+ if self.warn:
+ with assert_warns(DeprecationWarning) as exc:
+ assert self.conv(val) == expected
+ else:
+ assert self.conv(val) == expected
+
def _check(self, val, expected):
+ """Takes valid non-deprecated inputs for converters,
+ runs converters on inputs, checks correctness of outputs,
+ warnings and errors"""
assert self.conv(val) == expected
if self.allow_bytes:
@@ -33,13 +45,13 @@ class StringConverterTestCase:
self._check_value_error(val[:1])
self._check_value_error(val + '\0')
else:
- assert self.conv(val[:1]) == expected
+ self._check_conv_assert_warn(val[:1], expected)
if self.case_insensitive:
if val != val.lower():
- assert self.conv(val.lower()) == expected
+ self._check_conv_assert_warn(val.lower(), expected)
if val != val.upper():
- assert self.conv(val.upper()) == expected
+ self._check_conv_assert_warn(val.upper(), expected)
else:
if val != val.lower():
self._check_value_error(val.lower())
@@ -69,6 +81,8 @@ class StringConverterTestCase:
class TestByteorderConverter(StringConverterTestCase):
""" Tests of PyArray_ByteorderConverter """
conv = mt.run_byteorder_converter
+ warn = False
+
def test_valid(self):
for s in ['big', '>']:
self._check(s, 'NPY_BIG')
@@ -85,10 +99,12 @@ class TestByteorderConverter(StringConverterTestCase):
class TestSortkindConverter(StringConverterTestCase):
""" Tests of PyArray_SortkindConverter """
conv = mt.run_sortkind_converter
+ warn = False
+
def test_valid(self):
- self._check('quick', 'NPY_QUICKSORT')
- self._check('heap', 'NPY_HEAPSORT')
- self._check('merge', 'NPY_STABLESORT') # alias
+ self._check('quicksort', 'NPY_QUICKSORT')
+ self._check('heapsort', 'NPY_HEAPSORT')
+ self._check('mergesort', 'NPY_STABLESORT') # alias
self._check('stable', 'NPY_STABLESORT')
@@ -113,6 +129,8 @@ class TestSearchsideConverter(StringConverterTestCase):
class TestOrderConverter(StringConverterTestCase):
""" Tests of PyArray_OrderConverter """
conv = mt.run_order_converter
+ warn = False
+
def test_valid(self):
self._check('c', 'NPY_CORDER')
self._check('f', 'NPY_FORTRANORDER')
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index 523638a35..9dcf4a9c9 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -313,19 +313,14 @@ class TestBinaryReprInsufficientWidthParameterForRepresentation(_DeprecationTest
class TestNumericStyleTypecodes(_DeprecationTestCase):
"""
- Deprecate the old numeric-style dtypes, which are especially
- confusing for complex types, e.g. Complex32 -> complex64. When the
- deprecation cycle is complete, the check for the strings should be
- removed from PyArray_DescrConverter in descriptor.c, and the
- deprecated keys should not be added as capitalized aliases in
- _add_aliases in numerictypes.py.
+ Most numeric style typecodes were previously deprecated (and removed)
+ in 1.20. This also deprecates the remaining ones.
"""
+ # 2020-06-09, NumPy 1.20
def test_all_dtypes(self):
- deprecated_types = [
- 'Bool', 'Complex32', 'Complex64', 'Float16', 'Float32', 'Float64',
- 'Int8', 'Int16', 'Int32', 'Int64', 'Object0', 'Timedelta64',
- 'UInt8', 'UInt16', 'UInt32', 'UInt64', 'Void0'
- ]
+ deprecated_types = ['Bytes0', 'Datetime64', 'Str0']
+ # Depending on intp size, either Uint32 or Uint64 is defined:
+ deprecated_types.append(f"U{np.dtype(np.intp).name}")
for dt in deprecated_types:
self.assert_deprecated(np.dtype, exceptions=(TypeError,),
args=(dt,))
@@ -438,14 +433,6 @@ class TestGeneratorSum(_DeprecationTestCase):
self.assert_deprecated(np.sum, args=((i for i in range(5)),))
-class TestSctypeNA(_VisibleDeprecationTestCase):
- # 2018-06-24, 1.16
- def test_sctypeNA(self):
- self.assert_deprecated(lambda: np.sctypeNA['?'])
- self.assert_deprecated(lambda: np.typeNA['?'])
- self.assert_deprecated(lambda: np.typeNA.get('?'))
-
-
class TestPositiveOnNonNumerical(_DeprecationTestCase):
# 2018-06-28, 1.16.0
def test_positive_on_non_number(self):
@@ -645,3 +632,13 @@ class TestIncorrectAdvancedIndexWithEmptyResult(_DeprecationTestCase):
self.assert_not_deprecated(arr.__getitem__, args=(index,))
self.assert_not_deprecated(arr.__setitem__,
args=(index, np.empty((2, 0, 2))))
+
+
+class TestNonExactMatchDeprecation(_DeprecationTestCase):
+ # 2020-04-22
+ def test_non_exact_match(self):
+ arr = np.array([[3, 6, 6], [4, 5, 1]])
+ # misspelt mode check
+ self.assert_deprecated(lambda: np.ravel_multi_index(arr, (7, 6), mode='Cilp'))
+ # using completely different word with first character as R
+ self.assert_deprecated(lambda: np.searchsorted(arr[0], 4, side='Random'))
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index 73aa01de6..2e2b0dbe2 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -86,6 +86,15 @@ class TestBuiltin:
assert_raises(TypeError, np.dtype, 'q8')
assert_raises(TypeError, np.dtype, 'Q8')
+ @pytest.mark.parametrize("dtype",
+ ['Bool', 'Complex32', 'Complex64', 'Float16', 'Float32', 'Float64',
+ 'Int8', 'Int16', 'Int32', 'Int64', 'Object0', 'Timedelta64',
+ 'UInt8', 'UInt16', 'UInt32', 'UInt64', 'Void0',
+ "Float128", "Complex128"])
+ def test_numeric_style_types_are_invalid(self, dtype):
+ with assert_raises(TypeError):
+ np.dtype(dtype)
+
@pytest.mark.parametrize(
'value',
['m8', 'M8', 'datetime64', 'timedelta64',
@@ -1047,6 +1056,11 @@ def test_invalid_dtype_string():
assert_raises(TypeError, np.dtype, u'Fl\xfcgel')
+def test_keyword_argument():
+ # test for https://github.com/numpy/numpy/pull/16574#issuecomment-642660971
+ assert np.dtype(dtype=np.float64) == np.dtype(np.float64)
+
+
class TestFromDTypeAttribute:
def test_simple(self):
class dt:
@@ -1324,4 +1338,3 @@ class TestFromCTypes:
pair_type = np.dtype('{},{}'.format(*pair))
expected = np.dtype([('f0', pair[0]), ('f1', pair[1])])
assert_equal(pair_type, expected)
-
diff --git a/numpy/core/tests/test_einsum.py b/numpy/core/tests/test_einsum.py
index da84735a0..c697d0c2d 100644
--- a/numpy/core/tests/test_einsum.py
+++ b/numpy/core/tests/test_einsum.py
@@ -94,6 +94,10 @@ class TestEinsum:
b = np.ones((3, 4, 5))
np.einsum('aabcb,abc', a, b)
+ # Check order kwarg, asanyarray allows 1d to pass through
+ assert_raises(ValueError, np.einsum, "i->i", np.arange(6).reshape(-1, 1),
+ optimize=do_opt, order='d')
+
def test_einsum_views(self):
# pass-through
for do_opt in [True, False]:
@@ -876,6 +880,41 @@ class TestEinsum:
g = np.arange(64).reshape(2, 4, 8)
self.optimize_compare('obk,ijk->ioj', operands=[g, g])
+ def test_output_order(self):
+ # Ensure output order is respected for optimize cases, the below
+ # conraction should yield a reshaped tensor view
+ # gh-16415
+
+ a = np.ones((2, 3, 5), order='F')
+ b = np.ones((4, 3), order='F')
+
+ for opt in [True, False]:
+ tmp = np.einsum('...ft,mf->...mt', a, b, order='a', optimize=opt)
+ assert_(tmp.flags.f_contiguous)
+
+ tmp = np.einsum('...ft,mf->...mt', a, b, order='f', optimize=opt)
+ assert_(tmp.flags.f_contiguous)
+
+ tmp = np.einsum('...ft,mf->...mt', a, b, order='c', optimize=opt)
+ assert_(tmp.flags.c_contiguous)
+
+ tmp = np.einsum('...ft,mf->...mt', a, b, order='k', optimize=opt)
+ assert_(tmp.flags.c_contiguous is False)
+ assert_(tmp.flags.f_contiguous is False)
+
+ tmp = np.einsum('...ft,mf->...mt', a, b, optimize=opt)
+ assert_(tmp.flags.c_contiguous is False)
+ assert_(tmp.flags.f_contiguous is False)
+
+ c = np.ones((4, 3), order='C')
+ for opt in [True, False]:
+ tmp = np.einsum('...ft,mf->...mt', a, c, order='a', optimize=opt)
+ assert_(tmp.flags.c_contiguous)
+
+ d = np.ones((2, 3, 5), order='C')
+ for opt in [True, False]:
+ tmp = np.einsum('...ft,mf->...mt', d, c, order='a', optimize=opt)
+ assert_(tmp.flags.c_contiguous)
class TestEinsumPath:
def build_operands(self, string, size_dict=global_size_dict):
diff --git a/numpy/core/tests/test_function_base.py b/numpy/core/tests/test_function_base.py
index 2197ef0cd..62a9772c8 100644
--- a/numpy/core/tests/test_function_base.py
+++ b/numpy/core/tests/test_function_base.py
@@ -1,6 +1,6 @@
from numpy import (
logspace, linspace, geomspace, dtype, array, sctypes, arange, isnan,
- ndarray, sqrt, nextafter, stack
+ ndarray, sqrt, nextafter, stack, errstate
)
from numpy.testing import (
assert_, assert_equal, assert_raises, assert_array_equal, assert_allclose,
@@ -113,6 +113,40 @@ class TestGeomspace:
assert_array_equal(y, [-100, -10, -1])
assert_array_equal(y.imag, 0)
+ def test_boundaries_match_start_and_stop_exactly(self):
+ # make sure that the boundaries of the returned array exactly
+ # equal 'start' and 'stop' - this isn't obvious because
+ # np.exp(np.log(x)) isn't necessarily exactly equal to x
+ start = 0.3
+ stop = 20.3
+
+ y = geomspace(start, stop, num=1)
+ assert_equal(y[0], start)
+
+ y = geomspace(start, stop, num=1, endpoint=False)
+ assert_equal(y[0], start)
+
+ y = geomspace(start, stop, num=3)
+ assert_equal(y[0], start)
+ assert_equal(y[-1], stop)
+
+ y = geomspace(start, stop, num=3, endpoint=False)
+ assert_equal(y[0], start)
+
+ def test_nan_interior(self):
+ with errstate(invalid='ignore'):
+ y = geomspace(-3, 3, num=4)
+
+ assert_equal(y[0], -3.0)
+ assert_(isnan(y[1:-1]).all())
+ assert_equal(y[3], 3.0)
+
+ with errstate(invalid='ignore'):
+ y = geomspace(-3, 3, num=4, endpoint=False)
+
+ assert_equal(y[0], -3.0)
+ assert_(isnan(y[1:]).all())
+
def test_complex(self):
# Purely imaginary
y = geomspace(1j, 16j, num=5)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 1a8268eb8..e116077f9 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -2153,10 +2153,10 @@ class TestMethods:
# check double
a = np.array([0, 1, np.nan])
msg = "Test real searchsorted with nans, side='l'"
- b = a.searchsorted(a, side='l')
+ b = a.searchsorted(a, side='left')
assert_equal(b, np.arange(3), msg)
msg = "Test real searchsorted with nans, side='r'"
- b = a.searchsorted(a, side='r')
+ b = a.searchsorted(a, side='right')
assert_equal(b, np.arange(1, 4), msg)
# check keyword arguments
a.searchsorted(v=1)
@@ -2165,10 +2165,10 @@ class TestMethods:
a.real += [0, 0, 1, 1, 0, 1, np.nan, np.nan, np.nan]
a.imag += [0, 1, 0, 1, np.nan, np.nan, 0, 1, np.nan]
msg = "Test complex searchsorted with nans, side='l'"
- b = a.searchsorted(a, side='l')
+ b = a.searchsorted(a, side='left')
assert_equal(b, np.arange(9), msg)
msg = "Test complex searchsorted with nans, side='r'"
- b = a.searchsorted(a, side='r')
+ b = a.searchsorted(a, side='right')
assert_equal(b, np.arange(1, 10), msg)
msg = "Test searchsorted with little endian, side='l'"
a = np.array([0, 128], dtype='<i4')
@@ -2181,21 +2181,21 @@ class TestMethods:
# Check 0 elements
a = np.ones(0)
- b = a.searchsorted([0, 1, 2], 'l')
+ b = a.searchsorted([0, 1, 2], 'left')
assert_equal(b, [0, 0, 0])
- b = a.searchsorted([0, 1, 2], 'r')
+ b = a.searchsorted([0, 1, 2], 'right')
assert_equal(b, [0, 0, 0])
a = np.ones(1)
# Check 1 element
- b = a.searchsorted([0, 1, 2], 'l')
+ b = a.searchsorted([0, 1, 2], 'left')
assert_equal(b, [0, 0, 1])
- b = a.searchsorted([0, 1, 2], 'r')
+ b = a.searchsorted([0, 1, 2], 'right')
assert_equal(b, [0, 1, 1])
# Check all elements equal
a = np.ones(2)
- b = a.searchsorted([0, 1, 2], 'l')
+ b = a.searchsorted([0, 1, 2], 'left')
assert_equal(b, [0, 0, 2])
- b = a.searchsorted([0, 1, 2], 'r')
+ b = a.searchsorted([0, 1, 2], 'right')
assert_equal(b, [0, 2, 2])
# Test searching unaligned array
@@ -2204,21 +2204,21 @@ class TestMethods:
unaligned = aligned[1:].view(a.dtype)
unaligned[:] = a
# Test searching unaligned array
- b = unaligned.searchsorted(a, 'l')
+ b = unaligned.searchsorted(a, 'left')
assert_equal(b, a)
- b = unaligned.searchsorted(a, 'r')
+ b = unaligned.searchsorted(a, 'right')
assert_equal(b, a + 1)
# Test searching for unaligned keys
- b = a.searchsorted(unaligned, 'l')
+ b = a.searchsorted(unaligned, 'left')
assert_equal(b, a)
- b = a.searchsorted(unaligned, 'r')
+ b = a.searchsorted(unaligned, 'right')
assert_equal(b, a + 1)
# Test smart resetting of binsearch indices
a = np.arange(5)
- b = a.searchsorted([6, 5, 4], 'l')
+ b = a.searchsorted([6, 5, 4], 'left')
assert_equal(b, [5, 5, 4])
- b = a.searchsorted([6, 5, 4], 'r')
+ b = a.searchsorted([6, 5, 4], 'right')
assert_equal(b, [5, 5, 5])
# Test all type specific binary search functions
@@ -2233,16 +2233,16 @@ class TestMethods:
else:
a = np.arange(0, 5, dtype=dt)
out = np.arange(5)
- b = a.searchsorted(a, 'l')
+ b = a.searchsorted(a, 'left')
assert_equal(b, out)
- b = a.searchsorted(a, 'r')
+ b = a.searchsorted(a, 'right')
assert_equal(b, out + 1)
# Test empty array, use a fresh array to get warnings in
# valgrind if access happens.
e = np.ndarray(shape=0, buffer=b'', dtype=dt)
- b = e.searchsorted(a, 'l')
+ b = e.searchsorted(a, 'left')
assert_array_equal(b, np.zeros(len(a), dtype=np.intp))
- b = a.searchsorted(e, 'l')
+ b = a.searchsorted(e, 'left')
assert_array_equal(b, np.zeros(0, dtype=np.intp))
def test_searchsorted_unicode(self):
@@ -2297,9 +2297,9 @@ class TestMethods:
s = a.argsort()
k = [0, 1, 2, 3, 5]
expected = [0, 20, 40, 60, 80]
- assert_equal(a.searchsorted(k, side='l', sorter=s), expected)
+ assert_equal(a.searchsorted(k, side='left', sorter=s), expected)
expected = [20, 40, 60, 80, 100]
- assert_equal(a.searchsorted(k, side='r', sorter=s), expected)
+ assert_equal(a.searchsorted(k, side='right', sorter=s), expected)
# Test searching unaligned array
keys = np.arange(10)
@@ -2310,15 +2310,15 @@ class TestMethods:
unaligned = aligned[1:].view(a.dtype)
# Test searching unaligned array
unaligned[:] = a
- b = unaligned.searchsorted(keys, 'l', s)
+ b = unaligned.searchsorted(keys, 'left', s)
assert_equal(b, keys)
- b = unaligned.searchsorted(keys, 'r', s)
+ b = unaligned.searchsorted(keys, 'right', s)
assert_equal(b, keys + 1)
# Test searching for unaligned keys
unaligned[:] = keys
- b = a.searchsorted(unaligned, 'l', s)
+ b = a.searchsorted(unaligned, 'left', s)
assert_equal(b, keys)
- b = a.searchsorted(unaligned, 'r', s)
+ b = a.searchsorted(unaligned, 'right', s)
assert_equal(b, keys + 1)
# Test all type specific indirect binary search functions
@@ -2339,16 +2339,16 @@ class TestMethods:
# from np.intp in all platforms, to check for #4698
s = np.array([4, 2, 3, 0, 1], dtype=np.int16)
out = np.array([3, 4, 1, 2, 0], dtype=np.intp)
- b = a.searchsorted(a, 'l', s)
+ b = a.searchsorted(a, 'left', s)
assert_equal(b, out)
- b = a.searchsorted(a, 'r', s)
+ b = a.searchsorted(a, 'right', s)
assert_equal(b, out + 1)
# Test empty array, use a fresh array to get warnings in
# valgrind if access happens.
e = np.ndarray(shape=0, buffer=b'', dtype=dt)
- b = e.searchsorted(a, 'l', s[:0])
+ b = e.searchsorted(a, 'left', s[:0])
assert_array_equal(b, np.zeros(len(a), dtype=np.intp))
- b = a.searchsorted(e, 'l', s)
+ b = a.searchsorted(e, 'left', s)
assert_array_equal(b, np.zeros(0, dtype=np.intp))
# Test non-contiguous sorter array
@@ -2358,9 +2358,9 @@ class TestMethods:
srt[::2] = [4, 2, 3, 0, 1]
s = srt[::2]
out = np.array([3, 4, 1, 2, 0], dtype=np.intp)
- b = a.searchsorted(a, 'l', s)
+ b = a.searchsorted(a, 'left', s)
assert_equal(b, out)
- b = a.searchsorted(a, 'r', s)
+ b = a.searchsorted(a, 'right', s)
assert_equal(b, out + 1)
def test_searchsorted_return_type(self):
@@ -2370,10 +2370,10 @@ class TestMethods:
a = np.arange(5).view(A)
b = np.arange(1, 3).view(A)
s = np.arange(5).view(A)
- assert_(not isinstance(a.searchsorted(b, 'l'), A))
- assert_(not isinstance(a.searchsorted(b, 'r'), A))
- assert_(not isinstance(a.searchsorted(b, 'l', s), A))
- assert_(not isinstance(a.searchsorted(b, 'r', s), A))
+ assert_(not isinstance(a.searchsorted(b, 'left'), A))
+ assert_(not isinstance(a.searchsorted(b, 'right'), A))
+ assert_(not isinstance(a.searchsorted(b, 'left', s), A))
+ assert_(not isinstance(a.searchsorted(b, 'right', s), A))
def test_argpartition_out_of_range(self):
# Test out of range values in kth raise an error, gh-5469
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index 96a6d810f..cf18a5d93 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -42,13 +42,6 @@ class TestRegression:
b = pickle.load(f)
assert_array_equal(a, b)
- def test_typeNA(self):
- # Issue gh-515
- with suppress_warnings() as sup:
- sup.filter(np.VisibleDeprecationWarning)
- assert_equal(np.typeNA[np.int64], 'Int64')
- assert_equal(np.typeNA[np.uint64], 'UInt64')
-
def test_dtype_names(self):
# Ticket #35
# Should succeed
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 91acd6ac3..f836af168 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -890,15 +890,17 @@ class TestAVXFloat32Transcendental:
sizes = np.arange(2,100)
for ii in sizes:
x_f32 = np.float32(np.random.uniform(low=0.01,high=88.1,size=ii))
+ x_f32_large = x_f32.copy()
+ x_f32_large[3:-1:4] = 120000.0
exp_true = np.exp(x_f32)
log_true = np.log(x_f32)
- sin_true = np.sin(x_f32)
- cos_true = np.cos(x_f32)
+ sin_true = np.sin(x_f32_large)
+ cos_true = np.cos(x_f32_large)
for jj in strides:
assert_array_almost_equal_nulp(np.exp(x_f32[::jj]), exp_true[::jj], nulp=2)
assert_array_almost_equal_nulp(np.log(x_f32[::jj]), log_true[::jj], nulp=2)
- assert_array_almost_equal_nulp(np.sin(x_f32[::jj]), sin_true[::jj], nulp=2)
- assert_array_almost_equal_nulp(np.cos(x_f32[::jj]), cos_true[::jj], nulp=2)
+ assert_array_almost_equal_nulp(np.sin(x_f32_large[::jj]), sin_true[::jj], nulp=2)
+ assert_array_almost_equal_nulp(np.cos(x_f32_large[::jj]), cos_true[::jj], nulp=2)
class TestLogAddExp(_FilterInvalids):
def test_logaddexp_values(self):
diff --git a/numpy/core/tests/test_umath_accuracy.py b/numpy/core/tests/test_umath_accuracy.py
index e3c2eb025..33080edbb 100644
--- a/numpy/core/tests/test_umath_accuracy.py
+++ b/numpy/core/tests/test_umath_accuracy.py
@@ -57,9 +57,3 @@ class TestAccuracy:
outval = outval[perm]
maxulperr = data_subset['ulperr'].max()
assert_array_max_ulp(npfunc(inval), outval, maxulperr)
-
- def test_ignore_nan_ulperror(self):
- # Ignore ULP differences between various NAN's
- nan1_f32 = np.array(str_to_float('0xffffffff'), dtype=np.float32)
- nan2_f32 = np.array(str_to_float('0x7fddbfbf'), dtype=np.float32)
- assert_array_max_ulp(nan1_f32, nan2_f32, 0)
diff --git a/numpy/doc/dispatch.py b/numpy/doc/dispatch.py
index ba76a43ae..af70ed836 100644
--- a/numpy/doc/dispatch.py
+++ b/numpy/doc/dispatch.py
@@ -267,5 +267,5 @@ Refer to the `dask source code <https://github.com/dask/dask>`_ and
`cupy source code <https://github.com/cupy/cupy>`_ for more fully-worked
examples of custom array containers.
-See also `NEP 18 <http://www.numpy.org/neps/nep-0018-array-function-protocol.html>`_.
+See also :doc:`NEP 18<neps:nep-0018-array-function-protocol>`.
"""
diff --git a/numpy/f2py/cb_rules.py b/numpy/f2py/cb_rules.py
index 87887c152..3068dc897 100644
--- a/numpy/f2py/cb_rules.py
+++ b/numpy/f2py/cb_rules.py
@@ -33,119 +33,154 @@ cb_routine_rules = {
'cbtypedefs': 'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);',
'body': """
#begintitle#
-PyObject *#name#_capi = NULL;/*was Py_None*/
-PyTupleObject *#name#_args_capi = NULL;
-int #name#_nofargs = 0;
-jmp_buf #name#_jmpbuf;
+typedef struct {
+ PyObject *capi;
+ PyTupleObject *args_capi;
+ int nofargs;
+ jmp_buf jmpbuf;
+} #name#_t;
+
+#if defined(F2PY_THREAD_LOCAL_DECL) && !defined(F2PY_USE_PYTHON_TLS)
+
+static F2PY_THREAD_LOCAL_DECL #name#_t *_active_#name# = NULL;
+
+static #name#_t *swap_active_#name#(#name#_t *ptr) {
+ #name#_t *prev = _active_#name#;
+ _active_#name# = ptr;
+ return prev;
+}
+
+static #name#_t *get_active_#name#(void) {
+ return _active_#name#;
+}
+
+#else
+
+static #name#_t *swap_active_#name#(#name#_t *ptr) {
+ char *key = "__f2py_cb_#name#";
+ return (#name#_t *)F2PySwapThreadLocalCallbackPtr(key, ptr);
+}
+
+static #name#_t *get_active_#name#(void) {
+ char *key = "__f2py_cb_#name#";
+ return (#name#_t *)F2PyGetThreadLocalCallbackPtr(key);
+}
+
+#endif
+
/*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/
#static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) {
-\tPyTupleObject *capi_arglist = #name#_args_capi;
-\tPyObject *capi_return = NULL;
-\tPyObject *capi_tmp = NULL;
-\tPyObject *capi_arglist_list = NULL;
-\tint capi_j,capi_i = 0;
-\tint capi_longjmp_ok = 1;
+ #name#_t *cb;
+ PyTupleObject *capi_arglist = NULL;
+ PyObject *capi_return = NULL;
+ PyObject *capi_tmp = NULL;
+ PyObject *capi_arglist_list = NULL;
+ int capi_j,capi_i = 0;
+ int capi_longjmp_ok = 1;
#decl#
#ifdef F2PY_REPORT_ATEXIT
f2py_cb_start_clock();
#endif
-\tCFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\");
-\tCFUNCSMESSPY(\"cb:#name#_capi=\",#name#_capi);
-\tif (#name#_capi==NULL) {
-\t\tcapi_longjmp_ok = 0;
-\t\t#name#_capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\");
-\t}
-\tif (#name#_capi==NULL) {
-\t\tPyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\");
-\t\tgoto capi_fail;
-\t}
-\tif (F2PyCapsule_Check(#name#_capi)) {
-\t#name#_typedef #name#_cptr;
-\t#name#_cptr = F2PyCapsule_AsVoidPtr(#name#_capi);
-\t#returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#);
-\t#return#
-\t}
-\tif (capi_arglist==NULL) {
-\t\tcapi_longjmp_ok = 0;
-\t\tcapi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\");
-\t\tif (capi_tmp) {
-\t\t\tcapi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp);
-\t\t\tif (capi_arglist==NULL) {
-\t\t\t\tPyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\");
-\t\t\t\tgoto capi_fail;
-\t\t\t}
-\t\t} else {
-\t\t\tPyErr_Clear();
-\t\t\tcapi_arglist = (PyTupleObject *)Py_BuildValue(\"()\");
-\t\t}
-\t}
-\tif (capi_arglist == NULL) {
-\t\tPyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\");
-\t\tgoto capi_fail;
-\t}
+ cb = get_active_#name#();
+ capi_arglist = cb->args_capi;
+ CFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\");
+ CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi);
+ if (cb->capi==NULL) {
+ capi_longjmp_ok = 0;
+ cb->capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\");
+ }
+ if (cb->capi==NULL) {
+ PyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\");
+ goto capi_fail;
+ }
+ if (F2PyCapsule_Check(cb->capi)) {
+ #name#_typedef #name#_cptr;
+ #name#_cptr = F2PyCapsule_AsVoidPtr(cb->capi);
+ #returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#);
+ #return#
+ }
+ if (capi_arglist==NULL) {
+ capi_longjmp_ok = 0;
+ capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\");
+ if (capi_tmp) {
+ capi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp);
+ if (capi_arglist==NULL) {
+ PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\");
+ goto capi_fail;
+ }
+ } else {
+ PyErr_Clear();
+ capi_arglist = (PyTupleObject *)Py_BuildValue(\"()\");
+ }
+ }
+ if (capi_arglist == NULL) {
+ PyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\");
+ goto capi_fail;
+ }
#setdims#
#ifdef PYPY_VERSION
#define CAPI_ARGLIST_SETITEM(idx, value) PyList_SetItem((PyObject *)capi_arglist_list, idx, value)
-\tcapi_arglist_list = PySequence_List(capi_arglist);
-\tif (capi_arglist_list == NULL) goto capi_fail;
+ capi_arglist_list = PySequence_List(capi_arglist);
+ if (capi_arglist_list == NULL) goto capi_fail;
#else
#define CAPI_ARGLIST_SETITEM(idx, value) PyTuple_SetItem((PyObject *)capi_arglist, idx, value)
#endif
#pyobjfrom#
#undef CAPI_ARGLIST_SETITEM
#ifdef PYPY_VERSION
-\tCFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist_list);
+ CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist_list);
#else
-\tCFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist);
+ CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist);
#endif
-\tCFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\");
+ CFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\");
#ifdef F2PY_REPORT_ATEXIT
f2py_cb_start_call_clock();
#endif
#ifdef PYPY_VERSION
-\tcapi_return = PyObject_CallObject(#name#_capi,(PyObject *)capi_arglist_list);
-\tPy_DECREF(capi_arglist_list);
-\tcapi_arglist_list = NULL;
+ capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist_list);
+ Py_DECREF(capi_arglist_list);
+ capi_arglist_list = NULL;
#else
-\tcapi_return = PyObject_CallObject(#name#_capi,(PyObject *)capi_arglist);
+ capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist);
#endif
#ifdef F2PY_REPORT_ATEXIT
f2py_cb_stop_call_clock();
#endif
-\tCFUNCSMESSPY(\"cb:capi_return=\",capi_return);
-\tif (capi_return == NULL) {
-\t\tfprintf(stderr,\"capi_return is NULL\\n\");
-\t\tgoto capi_fail;
-\t}
-\tif (capi_return == Py_None) {
-\t\tPy_DECREF(capi_return);
-\t\tcapi_return = Py_BuildValue(\"()\");
-\t}
-\telse if (!PyTuple_Check(capi_return)) {
-\t\tcapi_return = Py_BuildValue(\"(N)\",capi_return);
-\t}
-\tcapi_j = PyTuple_Size(capi_return);
-\tcapi_i = 0;
+ CFUNCSMESSPY(\"cb:capi_return=\",capi_return);
+ if (capi_return == NULL) {
+ fprintf(stderr,\"capi_return is NULL\\n\");
+ goto capi_fail;
+ }
+ if (capi_return == Py_None) {
+ Py_DECREF(capi_return);
+ capi_return = Py_BuildValue(\"()\");
+ }
+ else if (!PyTuple_Check(capi_return)) {
+ capi_return = Py_BuildValue(\"(N)\",capi_return);
+ }
+ capi_j = PyTuple_Size(capi_return);
+ capi_i = 0;
#frompyobj#
-\tCFUNCSMESS(\"cb:#name#:successful\\n\");
-\tPy_DECREF(capi_return);
+ CFUNCSMESS(\"cb:#name#:successful\\n\");
+ Py_DECREF(capi_return);
#ifdef F2PY_REPORT_ATEXIT
f2py_cb_stop_clock();
#endif
-\tgoto capi_return_pt;
+ goto capi_return_pt;
capi_fail:
-\tfprintf(stderr,\"Call-back #name# failed.\\n\");
-\tPy_XDECREF(capi_return);
-\tPy_XDECREF(capi_arglist_list);
-\tif (capi_longjmp_ok)
-\t\tlongjmp(#name#_jmpbuf,-1);
+ fprintf(stderr,\"Call-back #name# failed.\\n\");
+ Py_XDECREF(capi_return);
+ Py_XDECREF(capi_arglist_list);
+ if (capi_longjmp_ok) {
+ longjmp(cb->jmpbuf,-1);
+ }
capi_return_pt:
-\t;
+ ;
#return#
}
#endtitle#
""",
- 'need': ['setjmp.h', 'CFUNCSMESS'],
+ 'need': ['setjmp.h', 'CFUNCSMESS', 'F2PY_THREAD_LOCAL_DECL'],
'maxnofargs': '#maxnofargs#',
'nofoptargs': '#nofoptargs#',
'docstr': """\
@@ -188,26 +223,26 @@ cb_rout_rules = [
'latexdocstrcbs': '\\noindent Call-back functions:',
'routnote': {hasnote: '--- #note#', l_not(hasnote): ''},
}, { # Function
- 'decl': '\t#ctype# return_value;',
- 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting return_value->");'},
- '\tif (capi_j>capi_i)\n\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n");',
+ 'decl': ' #ctype# return_value;',
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'},
+ ' if (capi_j>capi_i)\n GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n");',
{debugcapi:
- '\tfprintf(stderr,"#showvalueformat#.\\n",return_value);'}
+ ' fprintf(stderr,"#showvalueformat#.\\n",return_value);'}
],
'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, 'GETSCALARFROMPYTUPLE'],
- 'return': '\treturn return_value;',
+ 'return': ' return return_value;',
'_check': l_and(isfunction, l_not(isstringfunction), l_not(iscomplexfunction))
},
{ # String function
- 'pyobjfrom': {debugcapi: '\tfprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'},
+ 'pyobjfrom': {debugcapi: ' fprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'},
'args': '#ctype# return_value,int return_value_len',
'args_nm': 'return_value,&return_value_len',
'args_td': '#ctype# ,int',
- 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting return_value->\\"");'},
- """\tif (capi_j>capi_i)
-\t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);""",
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting return_value->\\"");'},
+ """ if (capi_j>capi_i)
+ GETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);""",
{debugcapi:
- '\tfprintf(stderr,"#showvalueformat#\\".\\n",return_value);'}
+ ' fprintf(stderr,"#showvalueformat#\\".\\n",return_value);'}
],
'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
'string.h', 'GETSTRFROMPYTUPLE'],
@@ -232,32 +267,32 @@ return_value
""",
'decl': """
#ifdef F2PY_CB_RETURNCOMPLEX
-\t#ctype# return_value;
+ #ctype# return_value;
#endif
""",
- 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting return_value->");'},
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'},
"""\
-\tif (capi_j>capi_i)
+ if (capi_j>capi_i)
#ifdef F2PY_CB_RETURNCOMPLEX
-\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
+ GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
#else
-\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
+ GETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
#endif
""",
{debugcapi: """
#ifdef F2PY_CB_RETURNCOMPLEX
-\tfprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i);
+ fprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i);
#else
-\tfprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i);
+ fprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i);
#endif
"""}
],
'return': """
#ifdef F2PY_CB_RETURNCOMPLEX
-\treturn return_value;
+ return return_value;
#else
-\treturn;
+ return;
#endif
""",
'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
@@ -314,61 +349,61 @@ cb_arg_rules = [
'strarglens_nm': {isstring: ',#varname_i#_cb_len'},
},
{ # Scalars
- 'decl': {l_not(isintent_c): '\t#ctype# #varname_i#=(*#varname_i#_cb_capi);'},
+ 'decl': {l_not(isintent_c): ' #ctype# #varname_i#=(*#varname_i#_cb_capi);'},
'error': {l_and(isintent_c, isintent_out,
throw_error('intent(c,out) is forbidden for callback scalar arguments')):
''},
- 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting #varname#->");'},
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'},
{isintent_out:
- '\tif (capi_j>capi_i)\n\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname_i#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'},
+ ' if (capi_j>capi_i)\n GETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname_i#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'},
{l_and(debugcapi, l_and(l_not(iscomplex), isintent_c)):
- '\tfprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'},
+ ' fprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'},
{l_and(debugcapi, l_and(l_not(iscomplex), l_not( isintent_c))):
- '\tfprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'},
+ ' fprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'},
{l_and(debugcapi, l_and(iscomplex, isintent_c)):
- '\tfprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'},
+ ' fprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'},
{l_and(debugcapi, l_and(iscomplex, l_not( isintent_c))):
- '\tfprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'},
+ ' fprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'},
],
'need': [{isintent_out: ['#ctype#_from_pyobj', 'GETSCALARFROMPYTUPLE']},
{debugcapi: 'CFUNCSMESS'}],
'_check': isscalar
}, {
'pyobjfrom': [{isintent_in: """\
-\tif (#name#_nofargs>capi_i)
-\t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1(#varname_i#)))
-\t\t\tgoto capi_fail;"""},
+ if (cb->nofargs>capi_i)
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1(#varname_i#)))
+ goto capi_fail;"""},
{isintent_inout: """\
-\tif (#name#_nofargs>capi_i)
-\t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi)))
-\t\t\tgoto capi_fail;"""}],
+ if (cb->nofargs>capi_i)
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi)))
+ goto capi_fail;"""}],
'need': [{isintent_in: 'pyobj_from_#ctype#1'},
{isintent_inout: 'pyarr_from_p_#ctype#1'},
{iscomplex: '#ctype#'}],
'_check': l_and(isscalar, isintent_nothide),
'_optional': ''
}, { # String
- 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting #varname#->\\"");'},
- """\tif (capi_j>capi_i)
-\t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""",
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->\\"");'},
+ """ if (capi_j>capi_i)
+ GETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""",
{debugcapi:
- '\tfprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'},
+ ' fprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'},
],
'need': ['#ctype#', 'GETSTRFROMPYTUPLE',
{debugcapi: 'CFUNCSMESS'}, 'string.h'],
'_check': l_and(isstring, isintent_out)
}, {
- 'pyobjfrom': [{debugcapi: '\tfprintf(stderr,"debug-capi:cb:#varname#=\\"#showvalueformat#\\":%d:\\n",#varname_i#,#varname_i#_cb_len);'},
+ 'pyobjfrom': [{debugcapi: ' fprintf(stderr,"debug-capi:cb:#varname#=\\"#showvalueformat#\\":%d:\\n",#varname_i#,#varname_i#_cb_len);'},
{isintent_in: """\
-\tif (#name#_nofargs>capi_i)
-\t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len)))
-\t\t\tgoto capi_fail;"""},
+ if (cb->nofargs>capi_i)
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len)))
+ goto capi_fail;"""},
{isintent_inout: """\
-\tif (#name#_nofargs>capi_i) {
-\t\tint #varname_i#_cb_dims[] = {#varname_i#_cb_len};
-\t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims)))
-\t\t\tgoto capi_fail;
-\t}"""}],
+ if (cb->nofargs>capi_i) {
+ int #varname_i#_cb_dims[] = {#varname_i#_cb_len};
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims)))
+ goto capi_fail;
+ }"""}],
'need': [{isintent_in: 'pyobj_from_#ctype#1size'},
{isintent_inout: 'pyarr_from_p_#ctype#1'}],
'_check': l_and(isstring, isintent_nothide),
@@ -376,52 +411,52 @@ cb_arg_rules = [
},
# Array ...
{
- 'decl': '\tnpy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};',
- 'setdims': '\t#cbsetdims#;',
+ 'decl': ' npy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};',
+ 'setdims': ' #cbsetdims#;',
'_check': isarray,
'_depend': ''
},
{
- 'pyobjfrom': [{debugcapi: '\tfprintf(stderr,"debug-capi:cb:#varname#\\n");'},
+ 'pyobjfrom': [{debugcapi: ' fprintf(stderr,"debug-capi:cb:#varname#\\n");'},
{isintent_c: """\
-\tif (#name#_nofargs>capi_i) {
-\t\tint itemsize_ = #atype# == NPY_STRING ? 1 : 0;
-\t\t/*XXX: Hmm, what will destroy this array??? */
-\t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,itemsize_,NPY_ARRAY_CARRAY,NULL);
+ if (cb->nofargs>capi_i) {
+ int itemsize_ = #atype# == NPY_STRING ? 1 : 0;
+ /*XXX: Hmm, what will destroy this array??? */
+ PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,itemsize_,NPY_ARRAY_CARRAY,NULL);
""",
l_not(isintent_c): """\
-\tif (#name#_nofargs>capi_i) {
-\t\tint itemsize_ = #atype# == NPY_STRING ? 1 : 0;
-\t\t/*XXX: Hmm, what will destroy this array??? */
-\t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,itemsize_,NPY_ARRAY_FARRAY,NULL);
+ if (cb->nofargs>capi_i) {
+ int itemsize_ = #atype# == NPY_STRING ? 1 : 0;
+ /*XXX: Hmm, what will destroy this array??? */
+ PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,itemsize_,NPY_ARRAY_FARRAY,NULL);
""",
},
"""
-\t\tif (tmp_arr==NULL)
-\t\t\tgoto capi_fail;
-\t\tif (CAPI_ARGLIST_SETITEM(capi_i++,(PyObject *)tmp_arr))
-\t\t\tgoto capi_fail;
+ if (tmp_arr==NULL)
+ goto capi_fail;
+ if (CAPI_ARGLIST_SETITEM(capi_i++,(PyObject *)tmp_arr))
+ goto capi_fail;
}"""],
'_check': l_and(isarray, isintent_nothide, l_or(isintent_in, isintent_inout)),
'_optional': '',
}, {
- 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting #varname#->");'},
- """\tif (capi_j>capi_i) {
-\t\tPyArrayObject *rv_cb_arr = NULL;
-\t\tif ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail;
-\t\trv_cb_arr = array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""",
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'},
+ """ if (capi_j>capi_i) {
+ PyArrayObject *rv_cb_arr = NULL;
+ if ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail;
+ rv_cb_arr = array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""",
{isintent_c: '|F2PY_INTENT_C'},
""",capi_tmp);
-\t\tif (rv_cb_arr == NULL) {
-\t\t\tfprintf(stderr,\"rv_cb_arr is NULL\\n\");
-\t\t\tgoto capi_fail;
-\t\t}
-\t\tMEMCOPY(#varname_i#,PyArray_DATA(rv_cb_arr),PyArray_NBYTES(rv_cb_arr));
-\t\tif (capi_tmp != (PyObject *)rv_cb_arr) {
-\t\t\tPy_DECREF(rv_cb_arr);
-\t\t}
-\t}""",
- {debugcapi: '\tfprintf(stderr,"<-.\\n");'},
+ if (rv_cb_arr == NULL) {
+ fprintf(stderr,\"rv_cb_arr is NULL\\n\");
+ goto capi_fail;
+ }
+ MEMCOPY(#varname_i#,PyArray_DATA(rv_cb_arr),PyArray_NBYTES(rv_cb_arr));
+ if (capi_tmp != (PyObject *)rv_cb_arr) {
+ Py_DECREF(rv_cb_arr);
+ }
+ }""",
+ {debugcapi: ' fprintf(stderr,"<-.\\n");'},
],
'need': ['MEMCOPY', {iscomplexarray: '#ctype#'}],
'_check': l_and(isarray, isintent_out)
diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py
index f1ac214d4..ccbc9b0fb 100644
--- a/numpy/f2py/cfuncs.py
+++ b/numpy/f2py/cfuncs.py
@@ -543,6 +543,21 @@ cppmacros['OLDPYNUM'] = """\
#error You need to install NumPy version 0.13 or higher. See https://scipy.org/install.html
#endif
"""
+cppmacros["F2PY_THREAD_LOCAL_DECL"] = """\
+#ifndef F2PY_THREAD_LOCAL_DECL
+#if defined(_MSC_VER)
+#define F2PY_THREAD_LOCAL_DECL __declspec(thread)
+#elif defined(__STDC_VERSION__) \\
+ && (__STDC_VERSION__ >= 201112L) \\
+ && !defined(__STDC_NO_THREADS__)
+#include <threads.h>
+#define F2PY_THREAD_LOCAL_DECL thread_local
+#elif defined(__GNUC__) \\
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4)))
+#define F2PY_THREAD_LOCAL_DECL __thread
+#endif
+#endif
+"""
################# C functions ###############
cfuncs['calcarrindex'] = """\
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index ecfc71ae3..7b25b545a 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -266,18 +266,18 @@ static PyObject *#apiname#(const PyObject *capi_self,
PyObject *capi_args,
PyObject *capi_keywds,
#functype# (*f2py_func)(#callprotoargument#)) {
-\tPyObject * volatile capi_buildvalue = NULL;
-\tvolatile int f2py_success = 1;
+ PyObject * volatile capi_buildvalue = NULL;
+ volatile int f2py_success = 1;
#decl#
-\tstatic char *capi_kwlist[] = {#kwlist##kwlistopt##kwlistxa#NULL};
+ static char *capi_kwlist[] = {#kwlist##kwlistopt##kwlistxa#NULL};
#usercode#
#routdebugenter#
#ifdef F2PY_REPORT_ATEXIT
f2py_start_clock();
#endif
-\tif (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\\
-\t\t\"#argformat#|#keyformat##xaformat#:#pyname#\",\\
-\t\tcapi_kwlist#args_capi##keys_capi##keys_xa#))\n\t\treturn NULL;
+ if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\\
+ \"#argformat#|#keyformat##xaformat#:#pyname#\",\\
+ capi_kwlist#args_capi##keys_capi##keys_xa#))\n return NULL;
#frompyobj#
/*end of frompyobj*/
#ifdef F2PY_REPORT_ATEXIT
@@ -290,27 +290,27 @@ if (PyErr_Occurred())
f2py_stop_call_clock();
#endif
/*end of callfortranroutine*/
-\t\tif (f2py_success) {
+ if (f2py_success) {
#pyobjfrom#
/*end of pyobjfrom*/
-\t\tCFUNCSMESS(\"Building return value.\\n\");
-\t\tcapi_buildvalue = Py_BuildValue(\"#returnformat#\"#return#);
+ CFUNCSMESS(\"Building return value.\\n\");
+ capi_buildvalue = Py_BuildValue(\"#returnformat#\"#return#);
/*closepyobjfrom*/
#closepyobjfrom#
-\t\t} /*if (f2py_success) after callfortranroutine*/
+ } /*if (f2py_success) after callfortranroutine*/
/*cleanupfrompyobj*/
#cleanupfrompyobj#
-\tif (capi_buildvalue == NULL) {
+ if (capi_buildvalue == NULL) {
#routdebugfailure#
-\t} else {
+ } else {
#routdebugleave#
-\t}
-\tCFUNCSMESS(\"Freeing memory.\\n\");
+ }
+ CFUNCSMESS(\"Freeing memory.\\n\");
#freemem#
#ifdef F2PY_REPORT_ATEXIT
f2py_stop_clock();
#endif
-\treturn capi_buildvalue;
+ return capi_buildvalue;
}
#endtitle#
""",
@@ -749,36 +749,35 @@ arg_rules = [
'docstrcbs': '#cbdocstr#',
'latexdocstrcbs': '\\item[] #cblatexdocstr#',
'latexdocstropt': {isintent_nothide: '\\item[]{{}\\verb@#varname#_extra_args := () input tuple@{}} --- Extra arguments for call-back function {{}\\verb@#varname#@{}}.'},
- 'decl': ['\tPyObject *#varname#_capi = Py_None;',
- '\tPyTupleObject *#varname#_xa_capi = NULL;',
- '\tPyTupleObject *#varname#_args_capi = NULL;',
- '\tint #varname#_nofargs_capi = 0;',
+ 'decl': [' #cbname#_t #varname#_cb = { Py_None, NULL, 0 };',
+ ' #cbname#_t *#varname#_cb_ptr = &#varname#_cb;',
+ ' PyTupleObject *#varname#_xa_capi = NULL;',
{l_not(isintent_callback):
- '\t#cbname#_typedef #varname#_cptr;'}
+ ' #cbname#_typedef #varname#_cptr;'}
],
'kwlistxa': {isintent_nothide: '"#varname#_extra_args",'},
'argformat': {isrequired: 'O'},
'keyformat': {isoptional: 'O'},
'xaformat': {isintent_nothide: 'O!'},
- 'args_capi': {isrequired: ',&#varname#_capi'},
- 'keys_capi': {isoptional: ',&#varname#_capi'},
+ 'args_capi': {isrequired: ',&#varname#_cb.capi'},
+ 'keys_capi': {isoptional: ',&#varname#_cb.capi'},
'keys_xa': ',&PyTuple_Type,&#varname#_xa_capi',
- 'setjmpbuf': '(setjmp(#cbname#_jmpbuf))',
+ 'setjmpbuf': '(setjmp(#varname#_cb.jmpbuf))',
'callfortran': {l_not(isintent_callback): '#varname#_cptr,'},
'need': ['#cbname#', 'setjmp.h'],
'_check':isexternal
},
{
'frompyobj': [{l_not(isintent_callback): """\
-if(F2PyCapsule_Check(#varname#_capi)) {
- #varname#_cptr = F2PyCapsule_AsVoidPtr(#varname#_capi);
+if(F2PyCapsule_Check(#varname#_cb.capi)) {
+ #varname#_cptr = F2PyCapsule_AsVoidPtr(#varname#_cb.capi);
} else {
#varname#_cptr = #cbname#;
}
"""}, {isintent_callback: """\
-if (#varname#_capi==Py_None) {
- #varname#_capi = PyObject_GetAttrString(#modulename#_module,\"#varname#\");
- if (#varname#_capi) {
+if (#varname#_cb.capi==Py_None) {
+ #varname#_cb.capi = PyObject_GetAttrString(#modulename#_module,\"#varname#\");
+ if (#varname#_cb.capi) {
if (#varname#_xa_capi==NULL) {
if (PyObject_HasAttrString(#modulename#_module,\"#varname#_extra_args\")) {
PyObject* capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#varname#_extra_args\");
@@ -796,35 +795,29 @@ if (#varname#_capi==Py_None) {
}
}
}
- if (#varname#_capi==NULL) {
+ if (#varname#_cb.capi==NULL) {
PyErr_SetString(#modulename#_error,\"Callback #varname# not defined (as an argument or module #modulename# attribute).\\n\");
return NULL;
}
}
"""},
"""\
-\t#varname#_nofargs_capi = #cbname#_nofargs;
-\tif (create_cb_arglist(#varname#_capi,#varname#_xa_capi,#maxnofargs#,#nofoptargs#,&#cbname#_nofargs,&#varname#_args_capi,\"failed in processing argument list for call-back #varname#.\")) {
-\t\tjmp_buf #varname#_jmpbuf;""",
+ if (create_cb_arglist(#varname#_cb.capi,#varname#_xa_capi,#maxnofargs#,#nofoptargs#,&#varname#_cb.nofargs,&#varname#_cb.args_capi,\"failed in processing argument list for call-back #varname#.\")) {
+""",
{debugcapi: ["""\
-\t\tfprintf(stderr,\"debug-capi:Assuming %d arguments; at most #maxnofargs#(-#nofoptargs#) is expected.\\n\",#cbname#_nofargs);
-\t\tCFUNCSMESSPY(\"for #varname#=\",#cbname#_capi);""",
- {l_not(isintent_callback): """\t\tfprintf(stderr,\"#vardebugshowvalue# (call-back in C).\\n\",#cbname#);"""}]},
+ fprintf(stderr,\"debug-capi:Assuming %d arguments; at most #maxnofargs#(-#nofoptargs#) is expected.\\n\",#varname#_cb.nofargs);
+ CFUNCSMESSPY(\"for #varname#=\",#cbname#_capi);""",
+ {l_not(isintent_callback): """ fprintf(stderr,\"#vardebugshowvalue# (call-back in C).\\n\",#cbname#);"""}]},
"""\
-\t\tCFUNCSMESS(\"Saving jmpbuf for `#varname#`.\\n\");
-\t\tSWAP(#varname#_capi,#cbname#_capi,PyObject);
-\t\tSWAP(#varname#_args_capi,#cbname#_args_capi,PyTupleObject);
-\t\tmemcpy(&#varname#_jmpbuf,&#cbname#_jmpbuf,sizeof(jmp_buf));""",
+ CFUNCSMESS(\"Saving callback variables for `#varname#`.\\n\");
+ #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr);""",
],
'cleanupfrompyobj':
"""\
-\t\tCFUNCSMESS(\"Restoring jmpbuf for `#varname#`.\\n\");
-\t\t#cbname#_capi = #varname#_capi;
-\t\tPy_DECREF(#cbname#_args_capi);
-\t\t#cbname#_args_capi = #varname#_args_capi;
-\t\t#cbname#_nofargs = #varname#_nofargs_capi;
-\t\tmemcpy(&#cbname#_jmpbuf,&#varname#_jmpbuf,sizeof(jmp_buf));
-\t}""",
+ CFUNCSMESS(\"Restoring callback variables for `#varname#`.\\n\");
+ #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr);
+ Py_DECREF(#varname#_cb.args_capi);
+ }""",
'need': ['SWAP', 'create_cb_arglist'],
'_check':isexternal,
'_depend':''
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index b3a04bcf0..aa46c57d0 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -30,6 +30,68 @@ F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj)
return PyDict_SetItemString(dict, name, obj);
}
+/*
+ * Python-only fallback for thread-local callback pointers
+ */
+void *F2PySwapThreadLocalCallbackPtr(char *key, void *ptr)
+{
+ PyObject *local_dict, *value;
+ void *prev;
+
+ local_dict = PyThreadState_GetDict();
+ if (local_dict == NULL) {
+ Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyThreadState_GetDict failed");
+ }
+
+ value = PyDict_GetItemString(local_dict, key);
+ if (value != NULL) {
+ prev = PyLong_AsVoidPtr(value);
+ if (PyErr_Occurred()) {
+ Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
+ }
+ }
+ else {
+ prev = NULL;
+ }
+
+ value = PyLong_FromVoidPtr((void *)ptr);
+ if (value == NULL) {
+ Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyLong_FromVoidPtr failed");
+ }
+
+ if (PyDict_SetItemString(local_dict, key, value) != 0) {
+ Py_FatalError("F2PySwapThreadLocalCallbackPtr: PyDict_SetItemString failed");
+ }
+
+ Py_DECREF(value);
+
+ return prev;
+}
+
+void *F2PyGetThreadLocalCallbackPtr(char *key)
+{
+ PyObject *local_dict, *value;
+ void *prev;
+
+ local_dict = PyThreadState_GetDict();
+ if (local_dict == NULL) {
+ Py_FatalError("F2PyGetThreadLocalCallbackPtr: PyThreadState_GetDict failed");
+ }
+
+ value = PyDict_GetItemString(local_dict, key);
+ if (value != NULL) {
+ prev = PyLong_AsVoidPtr(value);
+ if (PyErr_Occurred()) {
+ Py_FatalError("F2PyGetThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
+ }
+ }
+ else {
+ prev = NULL;
+ }
+
+ return prev;
+}
+
/************************* FortranObject *******************************/
typedef PyObject *(*fortranfunc)(PyObject *,PyObject *,PyObject *,void *);
diff --git a/numpy/f2py/src/fortranobject.h b/numpy/f2py/src/fortranobject.h
index 5c382ab7b..d4cc10243 100644
--- a/numpy/f2py/src/fortranobject.h
+++ b/numpy/f2py/src/fortranobject.h
@@ -86,6 +86,9 @@ PyObject * F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *));
void * F2PyCapsule_AsVoidPtr(PyObject *obj);
int F2PyCapsule_Check(PyObject *ptr);
+extern void *F2PySwapThreadLocalCallbackPtr(char *key, void *ptr);
+extern void *F2PyGetThreadLocalCallbackPtr(char *key);
+
#define ISCONTIGUOUS(m) (PyArray_FLAGS(m) & NPY_ARRAY_C_CONTIGUOUS)
#define F2PY_INTENT_IN 1
#define F2PY_INTENT_INOUT 2
diff --git a/numpy/f2py/tests/test_callback.py b/numpy/f2py/tests/test_callback.py
index 4e29ab9fc..81650a819 100644
--- a/numpy/f2py/tests/test_callback.py
+++ b/numpy/f2py/tests/test_callback.py
@@ -2,6 +2,10 @@ import math
import textwrap
import sys
import pytest
+import threading
+import traceback
+import time
+import random
import numpy as np
from numpy.testing import assert_, assert_equal, IS_PYPY
@@ -161,3 +165,49 @@ cf2py intent(out) a
f = getattr(self.module, 'string_callback_array')
res = f(callback, cu, len(cu))
assert_(res == 0, repr(res))
+
+ def test_threadsafety(self):
+ # Segfaults if the callback handling is not threadsafe
+
+ errors = []
+
+ def cb():
+ # Sleep here to make it more likely for another thread
+ # to call their callback at the same time.
+ time.sleep(1e-3)
+
+ # Check reentrancy
+ r = self.module.t(lambda: 123)
+ assert_(r == 123)
+
+ return 42
+
+ def runner(name):
+ try:
+ for j in range(50):
+ r = self.module.t(cb)
+ assert_(r == 42)
+ self.check_function(name)
+ except Exception:
+ errors.append(traceback.format_exc())
+
+ threads = [threading.Thread(target=runner, args=(arg,))
+ for arg in ("t", "t2") for n in range(20)]
+
+ for t in threads:
+ t.start()
+
+ for t in threads:
+ t.join()
+
+ errors = "\n\n".join(errors)
+ if errors:
+ raise AssertionError(errors)
+
+
+class TestF77CallbackPythonTLS(TestF77Callback):
+ """
+ Callback tests using Python thread-local storage instead of
+ compiler-provided
+ """
+ options = ["-DF2PY_USE_PYTHON_TLS"]
diff --git a/numpy/lib/format.py b/numpy/lib/format.py
index 2afa4ac10..cb2d511af 100644
--- a/numpy/lib/format.py
+++ b/numpy/lib/format.py
@@ -156,8 +156,8 @@ names.
Notes
-----
The ``.npy`` format, including motivation for creating it and a comparison of
-alternatives, is described in the `"npy-format" NEP
-<https://www.numpy.org/neps/nep-0001-npy-format.html>`_, however details have
+alternatives, is described in the
+:doc:`"npy-format" NEP <neps:nep-0001-npy-format>`, however details have
evolved with time and this document is more current.
"""
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index 4ebca6360..cf6f4891c 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -1971,8 +1971,7 @@ class vectorize:
References
----------
- .. [1] NumPy Reference, section `Generalized Universal Function API
- <https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html>`_.
+ .. [1] :doc:`/reference/c-api/generalized-ufuncs`
Examples
--------
@@ -3120,7 +3119,7 @@ def i0(x):
.. [2] M. Abramowitz and I. A. Stegun, *Handbook of Mathematical
Functions*, 10th printing, New York: Dover, 1964, pp. 379.
http://www.math.sfu.ca/~cbm/aands/page_379.htm
- .. [3] http://kobesearch.cpan.org/htdocs/Math-Cephes/Math/Cephes.html
+ .. [3] https://metacpan.org/pod/distribution/Math-Cephes/lib/Math/Cephes.pod#i0:-Modified-Bessel-function-of-order-zero
Examples
--------
diff --git a/numpy/lib/mixins.py b/numpy/lib/mixins.py
index 50157069c..c81239f6b 100644
--- a/numpy/lib/mixins.py
+++ b/numpy/lib/mixins.py
@@ -68,7 +68,7 @@ class NDArrayOperatorsMixin:
It is useful for writing classes that do not inherit from `numpy.ndarray`,
but that should support arithmetic and numpy universal functions like
arrays as described in `A Mechanism for Overriding Ufuncs
- <../../neps/nep-0013-ufunc-overrides.html>`_.
+ <https://numpy.org/neps/nep-0013-ufunc-overrides.html>`_.
As an trivial example, consider this implementation of an ``ArrayLike``
class that simply wraps a NumPy array and ensures that the result of any
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 8d612b8ed..b5371f51a 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -21,6 +21,7 @@ Released for unlimited redistribution.
"""
# pylint: disable-msg=E1002
import builtins
+import inspect
import operator
import warnings
import textwrap
@@ -122,15 +123,8 @@ def doc_note(initialdoc, note):
if note is None:
return initialdoc
- notesplit = re.split(r'\n\s*?Notes\n\s*?-----', initialdoc)
-
- notedoc = """\
-Notes
- -----
- %s""" % note
-
- if len(notesplit) > 1:
- notedoc = '\n\n ' + notedoc + '\n'
+ notesplit = re.split(r'\n\s*?Notes\n\s*?-----', inspect.cleandoc(initialdoc))
+ notedoc = "\n\nNotes\n-----\n%s\n" % inspect.cleandoc(note)
return ''.join(notesplit[:1] + [notedoc] + notesplit[1:])
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index f86ebf551..8ede29da1 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -244,11 +244,6 @@ class _fromnxfunction:
the new masked array version of the function. A note on application
of the function to the mask is appended.
- .. warning::
- If the function docstring already contained a Notes section, the
- new docstring will have two Notes sections instead of appending a note
- to the existing section.
-
Parameters
----------
None
@@ -258,9 +253,9 @@ class _fromnxfunction:
doc = getattr(npfunc, '__doc__', None)
if doc:
sig = self.__name__ + ma.get_object_signature(npfunc)
- locdoc = "Notes\n-----\nThe function is applied to both the _data"\
- " and the _mask, if any."
- return '\n'.join((sig, doc, locdoc))
+ doc = ma.doc_note(doc, "The function is applied to both the _data "
+ "and the _mask, if any.")
+ return '\n\n'.join((sig, doc))
return
def __call__(self, *args, **params):
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index 6f34144bb..76a92f5ca 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -34,8 +34,8 @@ from numpy.ma.core import (
MAError, MaskError, MaskType, MaskedArray, abs, absolute, add, all,
allclose, allequal, alltrue, angle, anom, arange, arccos, arccosh, arctan2,
arcsin, arctan, argsort, array, asarray, choose, concatenate,
- conjugate, cos, cosh, count, default_fill_value, diag, divide, empty,
- empty_like, equal, exp, flatten_mask, filled, fix_invalid,
+ conjugate, cos, cosh, count, default_fill_value, diag, divide, doc_note,
+ empty, empty_like, equal, exp, flatten_mask, filled, fix_invalid,
flatten_structured_array, fromflex, getmask, getmaskarray, greater,
greater_equal, identity, inner, isMaskedArray, less, less_equal, log,
log10, make_mask, make_mask_descr, mask_or, masked, masked_array,
@@ -5283,3 +5283,33 @@ def test_mask_shape_assignment_does_not_break_masked():
b = np.ma.array(1, mask=a.mask)
b.shape = (1,)
assert_equal(a.mask.shape, ())
+
+@pytest.mark.skipif(sys.flags.optimize > 1,
+ reason="no docstrings present to inspect when PYTHONOPTIMIZE/Py_OptimizeFlag > 1")
+def test_doc_note():
+ def method(self):
+ """This docstring
+
+ Has multiple lines
+
+ And notes
+
+ Notes
+ -----
+ original note
+ """
+ pass
+
+ expected_doc = """This docstring
+
+Has multiple lines
+
+And notes
+
+Notes
+-----
+note
+
+original note"""
+
+ assert_equal(np.ma.core.doc_note(method.__doc__, "note"), expected_doc)
diff --git a/numpy/polynomial/_polybase.py b/numpy/polynomial/_polybase.py
index 30887b670..b5341ba37 100644
--- a/numpy/polynomial/_polybase.py
+++ b/numpy/polynomial/_polybase.py
@@ -919,10 +919,8 @@ class ABCPolyBase(abc.ABC):
----------
x : array_like, shape (M,)
x-coordinates of the M sample points ``(x[i], y[i])``.
- y : array_like, shape (M,) or (M, K)
- y-coordinates of the sample points. Several data sets of sample
- points sharing the same x-coordinates can be fitted at once by
- passing in a 2D-array that contains one dataset per column.
+ y : array_like, shape (M,)
+ y-coordinates of the M sample points ``(x[i], y[i])``.
deg : int or 1-D array_like
Degree(s) of the fitting polynomials. If `deg` is a single integer
all terms up to and including the `deg`'th term are included in the
diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py
index 4ddb0c688..431617414 100644
--- a/numpy/polynomial/chebyshev.py
+++ b/numpy/polynomial/chebyshev.py
@@ -104,7 +104,7 @@ References
----------
.. [1] A. T. Benjamin, et al., "Combinatorial Trigonometry with Chebyshev
Polynomials," *Journal of Statistical Planning and Inference 14*, 2008
- (preprint: https://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
+ (https://web.archive.org/web/20080221202153/https://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
"""
import numpy as np
diff --git a/numpy/py.typed b/numpy/py.typed
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/numpy/py.typed
diff --git a/numpy/random/_common.pyx b/numpy/random/_common.pyx
index ef1afac7c..6d77aed03 100644
--- a/numpy/random/_common.pyx
+++ b/numpy/random/_common.pyx
@@ -218,6 +218,20 @@ cdef np.ndarray int_to_array(object value, object name, object bits, object uint
return out
+cdef validate_output_shape(iter_shape, np.ndarray output):
+ cdef np.npy_intp *shape
+ cdef ndim, i
+ cdef bint error
+ dims = np.PyArray_DIMS(output)
+ ndim = np.PyArray_NDIM(output)
+ output_shape = tuple((dims[i] for i in range(ndim)))
+ if iter_shape != output_shape:
+ raise ValueError(
+ f"Output size {output_shape} is not compatible with broadcast "
+ f"dimensions of inputs {iter_shape}."
+ )
+
+
cdef check_output(object out, object dtype, object size):
if out is None:
return
@@ -404,6 +418,7 @@ cdef object cont_broadcast_1(void *func, void *state, object size, object lock,
randoms_data = <double *>np.PyArray_DATA(randoms)
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew2(randoms, a_arr)
+ validate_output_shape(it.shape, randoms)
with lock, nogil:
for i in range(n):
@@ -441,6 +456,8 @@ cdef object cont_broadcast_2(void *func, void *state, object size, object lock,
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+ validate_output_shape(it.shape, randoms)
+
with lock, nogil:
for i in range(n):
a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -482,6 +499,8 @@ cdef object cont_broadcast_3(void *func, void *state, object size, object lock,
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew4(randoms, a_arr, b_arr, c_arr)
+ validate_output_shape(it.shape, randoms)
+
with lock, nogil:
for i in range(n):
a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -611,6 +630,8 @@ cdef object discrete_broadcast_d(void *func, void *state, object size, object lo
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew2(randoms, a_arr)
+ validate_output_shape(it.shape, randoms)
+
with lock, nogil:
for i in range(n):
a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -645,6 +666,8 @@ cdef object discrete_broadcast_dd(void *func, void *state, object size, object l
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+ validate_output_shape(it.shape, randoms)
+
with lock, nogil:
for i in range(n):
a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -680,6 +703,8 @@ cdef object discrete_broadcast_di(void *func, void *state, object size, object l
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+ validate_output_shape(it.shape, randoms)
+
with lock, nogil:
for i in range(n):
a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -719,6 +744,8 @@ cdef object discrete_broadcast_iii(void *func, void *state, object size, object
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew4(randoms, a_arr, b_arr, c_arr)
+ validate_output_shape(it.shape, randoms)
+
with lock, nogil:
for i in range(n):
a_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -750,6 +777,8 @@ cdef object discrete_broadcast_i(void *func, void *state, object size, object lo
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew2(randoms, a_arr)
+ validate_output_shape(it.shape, randoms)
+
with lock, nogil:
for i in range(n):
a_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -923,6 +952,7 @@ cdef object cont_broadcast_1_f(void *func, bitgen_t *state, object size, object
randoms_data = <float *>np.PyArray_DATA(randoms)
n = np.PyArray_SIZE(randoms)
it = np.PyArray_MultiIterNew2(randoms, a_arr)
+ validate_output_shape(it.shape, randoms)
with lock, nogil:
for i in range(n):
diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx
index 2e54dce5f..0936ea2e8 100644
--- a/numpy/random/_generator.pyx
+++ b/numpy/random/_generator.pyx
@@ -2779,7 +2779,7 @@ cdef class Generator:
generate zero positive results.
>>> sum(rng.binomial(9, 0.1, 20000) == 0)/20000.
- # answer = 0.38885, or 38%.
+ # answer = 0.38885, or 39%.
"""
@@ -3345,7 +3345,8 @@ cdef class Generator:
def multivariate_normal(self, mean, cov, size=None, check_valid='warn',
tol=1e-8, *, method='svd'):
"""
- multivariate_normal(mean, cov, size=None, check_valid='warn', tol=1e-8)
+ multivariate_normal(mean, cov, size=None, check_valid='warn',
+ tol=1e-8, *, method='svd')
Draw random samples from a multivariate normal distribution.
diff --git a/numpy/random/bit_generator.pyx b/numpy/random/bit_generator.pyx
index f145ec13d..3c52a9933 100644
--- a/numpy/random/bit_generator.pyx
+++ b/numpy/random/bit_generator.pyx
@@ -382,13 +382,22 @@ cdef class SeedSequence():
-------
entropy_array : 1D uint32 array
"""
- # Convert run-entropy, program-entropy, and the spawn key into uint32
+ # Convert run-entropy and the spawn key into uint32
# arrays and concatenate them.
# We MUST have at least some run-entropy. The others are optional.
assert self.entropy is not None
run_entropy = _coerce_to_uint32_array(self.entropy)
spawn_entropy = _coerce_to_uint32_array(self.spawn_key)
+ if len(spawn_entropy) > 0 and len(run_entropy) < self.pool_size:
+ # Explicitly fill out the entropy with 0s to the pool size to avoid
+ # conflict with spawn keys. We changed this in 1.19.0 to fix
+ # gh-16539. In order to preserve stream-compatibility with
+ # unspawned SeedSequences with small entropy inputs, we only do
+ # this when a spawn_key is specified.
+ diff = self.pool_size - len(run_entropy)
+ run_entropy = np.concatenate(
+ [run_entropy, np.zeros(diff, dtype=np.uint32)])
entropy_array = np.concatenate([run_entropy, spawn_entropy])
return entropy_array
diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py
index f72b748ba..332b63198 100644
--- a/numpy/random/tests/test_generator_mt19937.py
+++ b/numpy/random/tests/test_generator_mt19937.py
@@ -2397,3 +2397,44 @@ def test_jumped(config):
md5 = hashlib.md5(key)
assert jumped.state["state"]["pos"] == config["jumped"]["pos"]
assert md5.hexdigest() == config["jumped"]["key_md5"]
+
+
+def test_broadcast_size_error():
+ mu = np.ones(3)
+ sigma = np.ones((4, 3))
+ size = (10, 4, 2)
+ assert random.normal(mu, sigma, size=(5, 4, 3)).shape == (5, 4, 3)
+ with pytest.raises(ValueError):
+ random.normal(mu, sigma, size=size)
+ with pytest.raises(ValueError):
+ random.normal(mu, sigma, size=(1, 3))
+ with pytest.raises(ValueError):
+ random.normal(mu, sigma, size=(4, 1, 1))
+ # 1 arg
+ shape = np.ones((4, 3))
+ with pytest.raises(ValueError):
+ random.standard_gamma(shape, size=size)
+ with pytest.raises(ValueError):
+ random.standard_gamma(shape, size=(3,))
+ with pytest.raises(ValueError):
+ random.standard_gamma(shape, size=3)
+ # Check out
+ out = np.empty(size)
+ with pytest.raises(ValueError):
+ random.standard_gamma(shape, out=out)
+
+ # 3 arg
+ a = random.chisquare(5, size=3)
+ b = random.chisquare(5, size=(4, 3))
+ c = random.chisquare(5, size=(5, 4, 3))
+ assert random.noncentral_f(a, b, c).shape == (5, 4, 3)
+ with pytest.raises(ValueError, match=r"Output size \(6, 5, 1, 1\) is"):
+ random.noncentral_f(a, b, c, size=(6, 5, 1, 1))
+
+
+def test_broadcast_size_scalar():
+ mu = np.ones(3)
+ sigma = np.ones(3)
+ random.normal(mu, sigma, size=3)
+ with pytest.raises(ValueError):
+ random.normal(mu, sigma, size=2)
diff --git a/numpy/random/tests/test_seed_sequence.py b/numpy/random/tests/test_seed_sequence.py
index fe23680ed..f08cf80fa 100644
--- a/numpy/random/tests/test_seed_sequence.py
+++ b/numpy/random/tests/test_seed_sequence.py
@@ -1,5 +1,5 @@
import numpy as np
-from numpy.testing import assert_array_equal
+from numpy.testing import assert_array_equal, assert_array_compare
from numpy.random import SeedSequence
@@ -52,3 +52,29 @@ def test_reference_data():
assert_array_equal(state, expected)
state64 = ss.generate_state(len(expected64), dtype=np.uint64)
assert_array_equal(state64, expected64)
+
+
+def test_zero_padding():
+ """ Ensure that the implicit zero-padding does not cause problems.
+ """
+ # Ensure that large integers are inserted in little-endian fashion to avoid
+ # trailing 0s.
+ ss0 = SeedSequence(42)
+ ss1 = SeedSequence(42 << 32)
+ assert_array_compare(
+ np.not_equal,
+ ss0.generate_state(4),
+ ss1.generate_state(4))
+
+ # Ensure backwards compatibility with the original 0.17 release for small
+ # integers and no spawn key.
+ expected42 = np.array([3444837047, 2669555309, 2046530742, 3581440988],
+ dtype=np.uint32)
+ assert_array_equal(SeedSequence(42).generate_state(4), expected42)
+
+ # Regression test for gh-16539 to ensure that the implicit 0s don't
+ # conflict with spawn keys.
+ assert_array_compare(
+ np.not_equal,
+ SeedSequence(42, spawn_key=(0,)).generate_state(4),
+ expected42)
diff --git a/numpy/setup.py b/numpy/setup.py
index 52db6a68b..c6498d101 100644
--- a/numpy/setup.py
+++ b/numpy/setup.py
@@ -18,6 +18,8 @@ def configuration(parent_package='',top_path=None):
config.add_subpackage('random')
config.add_subpackage('testing')
config.add_data_dir('doc')
+ config.add_data_files('py.typed')
+ config.add_data_files('*.pyi')
config.add_subpackage('tests')
config.make_config_py() # installs __config__.py
return config
diff --git a/numpy/testing/_private/nosetester.py b/numpy/testing/_private/nosetester.py
index bd6d002aa..57691a448 100644
--- a/numpy/testing/_private/nosetester.py
+++ b/numpy/testing/_private/nosetester.py
@@ -352,7 +352,7 @@ class NoseTester:
coverage : bool, optional
If True, report coverage of NumPy code. Default is False.
(This requires the
- `coverage module <https://nedbatchelder.com/code/modules/coveragehtml>`_).
+ `coverage module <https://pypi.org/project/coverage/>`_).
raise_warnings : None, str or sequence of warnings, optional
This specifies which warnings to configure as 'raise' instead
of being shown once during the test execution. Valid strings are:
diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py
index b899e94f4..6a6cc664a 100644
--- a/numpy/testing/tests/test_utils.py
+++ b/numpy/testing/tests/test_utils.py
@@ -941,6 +941,17 @@ class TestArrayAlmostEqualNulp:
assert_raises(AssertionError, assert_array_almost_equal_nulp,
x, y, nulp)
+ def test_float64_ignore_nan(self):
+ # Ignore ULP differences between various NAN's
+ # Note that MIPS may reverse quiet and signaling nans
+ # so we use the builtin version as a base.
+ offset = np.uint64(0xffffffff)
+ nan1_i64 = np.array(np.nan, dtype=np.float64).view(np.uint64)
+ nan2_i64 = nan1_i64 ^ offset # nan payload on MIPS is all ones.
+ nan1_f64 = nan1_i64.view(np.float64)
+ nan2_f64 = nan2_i64.view(np.float64)
+ assert_array_max_ulp(nan1_f64, nan2_f64, 0)
+
def test_float32_pass(self):
nulp = 5
x = np.linspace(-20, 20, 50, dtype=np.float32)
@@ -971,6 +982,17 @@ class TestArrayAlmostEqualNulp:
assert_raises(AssertionError, assert_array_almost_equal_nulp,
x, y, nulp)
+ def test_float32_ignore_nan(self):
+ # Ignore ULP differences between various NAN's
+ # Note that MIPS may reverse quiet and signaling nans
+ # so we use the builtin version as a base.
+ offset = np.uint32(0xffff)
+ nan1_i32 = np.array(np.nan, dtype=np.float32).view(np.uint32)
+ nan2_i32 = nan1_i32 ^ offset # nan payload on MIPS is all ones.
+ nan1_f32 = nan1_i32.view(np.float32)
+ nan2_f32 = nan2_i32.view(np.float32)
+ assert_array_max_ulp(nan1_f32, nan2_f32, 0)
+
def test_float16_pass(self):
nulp = 5
x = np.linspace(-4, 4, 10, dtype=np.float16)
@@ -1001,6 +1023,17 @@ class TestArrayAlmostEqualNulp:
assert_raises(AssertionError, assert_array_almost_equal_nulp,
x, y, nulp)
+ def test_float16_ignore_nan(self):
+ # Ignore ULP differences between various NAN's
+ # Note that MIPS may reverse quiet and signaling nans
+ # so we use the builtin version as a base.
+ offset = np.uint16(0xff)
+ nan1_i16 = np.array(np.nan, dtype=np.float16).view(np.uint16)
+ nan2_i16 = nan1_i16 ^ offset # nan payload on MIPS is all ones.
+ nan1_f16 = nan1_i16.view(np.float16)
+ nan2_f16 = nan2_i16.view(np.float16)
+ assert_array_max_ulp(nan1_f16, nan2_f16, 0)
+
def test_complex128_pass(self):
nulp = 5
x = np.linspace(-20, 20, 50, dtype=np.float64)
diff --git a/numpy/tests/setup.py b/numpy/tests/setup.py
new file mode 100644
index 000000000..f034cdf95
--- /dev/null
+++ b/numpy/tests/setup.py
@@ -0,0 +1,10 @@
+def configuration(parent_package='', top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('tests', parent_package, top_path)
+ config.add_data_dir('typing')
+ return config
+
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/tests/test_typing.py b/numpy/tests/test_typing.py
new file mode 100644
index 000000000..04ea3c64d
--- /dev/null
+++ b/numpy/tests/test_typing.py
@@ -0,0 +1,142 @@
+import importlib.util
+import itertools
+import os
+import re
+from collections import defaultdict
+
+import pytest
+try:
+ from mypy import api
+except ImportError:
+ NO_MYPY = True
+else:
+ NO_MYPY = False
+
+TESTS_DIR = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "typing",
+)
+PASS_DIR = os.path.join(TESTS_DIR, "pass")
+FAIL_DIR = os.path.join(TESTS_DIR, "fail")
+REVEAL_DIR = os.path.join(TESTS_DIR, "reveal")
+MYPY_INI = os.path.join(TESTS_DIR, "mypy.ini")
+CACHE_DIR = os.path.join(TESTS_DIR, ".mypy_cache")
+
+
+def get_test_cases(directory):
+ for root, _, files in os.walk(directory):
+ for fname in files:
+ if os.path.splitext(fname)[-1] == ".py":
+ fullpath = os.path.join(root, fname)
+ # Use relative path for nice py.test name
+ relpath = os.path.relpath(fullpath, start=directory)
+
+ yield pytest.param(
+ fullpath,
+ # Manually specify a name for the test
+ id=relpath,
+ )
+
+
+@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
+@pytest.mark.parametrize("path", get_test_cases(PASS_DIR))
+def test_success(path):
+ stdout, stderr, exitcode = api.run([
+ "--config-file",
+ MYPY_INI,
+ "--cache-dir",
+ CACHE_DIR,
+ path,
+ ])
+ assert exitcode == 0, stdout
+ assert re.match(r"Success: no issues found in \d+ source files?", stdout.strip())
+
+
+@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
+@pytest.mark.parametrize("path", get_test_cases(FAIL_DIR))
+def test_fail(path):
+ stdout, stderr, exitcode = api.run([
+ "--config-file",
+ MYPY_INI,
+ "--cache-dir",
+ CACHE_DIR,
+ path,
+ ])
+ assert exitcode != 0
+
+ with open(path) as fin:
+ lines = fin.readlines()
+
+ errors = defaultdict(lambda: "")
+ error_lines = stdout.rstrip("\n").split("\n")
+ assert re.match(
+ r"Found \d+ errors? in \d+ files? \(checked \d+ source files?\)",
+ error_lines[-1].strip(),
+ )
+ for error_line in error_lines[:-1]:
+ error_line = error_line.strip()
+ if not error_line:
+ continue
+
+ match = re.match(
+ r"^.+\.py:(?P<lineno>\d+): (error|note): .+$",
+ error_line,
+ )
+ if match is None:
+ raise ValueError(f"Unexpected error line format: {error_line}")
+ lineno = int(match.group('lineno'))
+ errors[lineno] += error_line
+
+ for i, line in enumerate(lines):
+ lineno = i + 1
+ if " E:" not in line and lineno not in errors:
+ continue
+
+ target_line = lines[lineno - 1]
+ if "# E:" in target_line:
+ marker = target_line.split("# E:")[-1].strip()
+ assert lineno in errors, f'Extra error "{marker}"'
+ assert marker in errors[lineno]
+ else:
+ pytest.fail(f"Error {repr(errors[lineno])} not found")
+
+
+@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
+@pytest.mark.parametrize("path", get_test_cases(REVEAL_DIR))
+def test_reveal(path):
+ stdout, stderr, exitcode = api.run([
+ "--config-file",
+ MYPY_INI,
+ "--cache-dir",
+ CACHE_DIR,
+ path,
+ ])
+
+ with open(path) as fin:
+ lines = fin.readlines()
+
+ for error_line in stdout.split("\n"):
+ error_line = error_line.strip()
+ if not error_line:
+ continue
+
+ match = re.match(
+ r"^.+\.py:(?P<lineno>\d+): note: .+$",
+ error_line,
+ )
+ if match is None:
+ raise ValueError(f"Unexpected reveal line format: {error_line}")
+ lineno = int(match.group('lineno'))
+ assert "Revealed type is" in error_line
+ marker = lines[lineno - 1].split("# E:")[-1].strip()
+ assert marker in error_line
+
+
+@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
+@pytest.mark.parametrize("path", get_test_cases(PASS_DIR))
+def test_code_runs(path):
+ path_without_extension, _ = os.path.splitext(path)
+ dirname, filename = path.split(os.sep)[-2:]
+ spec = importlib.util.spec_from_file_location(f"{dirname}.{filename}", path)
+ test_module = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(test_module)
diff --git a/numpy/tests/typing/fail/array_like.py b/numpy/tests/typing/fail/array_like.py
new file mode 100644
index 000000000..a5ef5795f
--- /dev/null
+++ b/numpy/tests/typing/fail/array_like.py
@@ -0,0 +1,22 @@
+from typing import Any, TYPE_CHECKING
+
+import numpy as np
+
+if TYPE_CHECKING:
+ from numpy.typing import ArrayLike
+else:
+ ArrayLike = Any
+
+
+class A:
+ pass
+
+
+x1: ArrayLike = (i for i in range(10)) # E: Incompatible types in assignment
+x2: ArrayLike = A() # E: Incompatible types in assignment
+x3: ArrayLike = {1: "foo", 2: "bar"} # E: Incompatible types in assignment
+
+scalar = np.int64(1)
+scalar.__array__(dtype=np.float64) # E: Unexpected keyword argument
+array = np.array([1])
+array.__array__(dtype=np.float64) # E: Unexpected keyword argument
diff --git a/numpy/tests/typing/fail/fromnumeric.py b/numpy/tests/typing/fail/fromnumeric.py
new file mode 100644
index 000000000..7455ce722
--- /dev/null
+++ b/numpy/tests/typing/fail/fromnumeric.py
@@ -0,0 +1,91 @@
+"""Tests for :mod:`numpy.core.fromnumeric`."""
+
+import numpy as np
+
+A = np.array(True, ndmin=2, dtype=bool)
+A.setflags(write=False)
+
+a = np.bool_(True)
+
+np.take(a, None) # E: No overload variant of "take" matches argument type
+np.take(a, axis=1.0) # E: No overload variant of "take" matches argument type
+np.take(A, out=1) # E: No overload variant of "take" matches argument type
+np.take(A, mode="bob") # E: No overload variant of "take" matches argument type
+
+np.reshape(a, None) # E: Argument 2 to "reshape" has incompatible type
+np.reshape(A, 1, order="bob") # E: Argument "order" to "reshape" has incompatible type
+
+np.choose(a, None) # E: No overload variant of "choose" matches argument type
+np.choose(a, out=1.0) # E: No overload variant of "choose" matches argument type
+np.choose(A, mode="bob") # E: No overload variant of "choose" matches argument type
+
+np.repeat(a, None) # E: Argument 2 to "repeat" has incompatible type
+np.repeat(A, 1, axis=1.0) # E: Argument "axis" to "repeat" has incompatible type
+
+np.swapaxes(A, None, 1) # E: Argument 2 to "swapaxes" has incompatible type
+np.swapaxes(A, 1, [0]) # E: Argument 3 to "swapaxes" has incompatible type
+
+np.transpose(A, axes=1.0) # E: Argument "axes" to "transpose" has incompatible type
+
+np.partition(a, None) # E: Argument 2 to "partition" has incompatible type
+np.partition(
+ a, 0, axis="bob" # E: Argument "axis" to "partition" has incompatible type
+)
+np.partition(
+ A, 0, kind="bob" # E: Argument "kind" to "partition" has incompatible type
+)
+np.partition(
+ A, 0, order=range(5) # E: Argument "order" to "partition" has incompatible type
+)
+
+np.argpartition( # E: No overload variant of "argpartition" matches argument type
+ a, None
+)
+np.argpartition( # E: No overload variant of "argpartition" matches argument type
+ a, 0, axis="bob"
+)
+np.argpartition( # E: No overload variant of "argpartition" matches argument type
+ A, 0, kind="bob"
+)
+np.argpartition(
+ A, 0, order=range(5) # E: Argument "order" to "argpartition" has incompatible type
+)
+
+np.sort(A, axis="bob") # E: Argument "axis" to "sort" has incompatible type
+np.sort(A, kind="bob") # E: Argument "kind" to "sort" has incompatible type
+np.sort(A, order=range(5)) # E: Argument "order" to "sort" has incompatible type
+
+np.argsort(A, axis="bob") # E: Argument "axis" to "argsort" has incompatible type
+np.argsort(A, kind="bob") # E: Argument "kind" to "argsort" has incompatible type
+np.argsort(A, order=range(5)) # E: Argument "order" to "argsort" has incompatible type
+
+np.argmax(A, axis="bob") # E: No overload variant of "argmax" matches argument type
+np.argmax(A, kind="bob") # E: No overload variant of "argmax" matches argument type
+
+np.argmin(A, axis="bob") # E: No overload variant of "argmin" matches argument type
+np.argmin(A, kind="bob") # E: No overload variant of "argmin" matches argument type
+
+np.searchsorted( # E: No overload variant of "searchsorted" matches argument type
+ A[0], 0, side="bob"
+)
+np.searchsorted( # E: No overload variant of "searchsorted" matches argument type
+ A[0], 0, sorter=1.0
+)
+
+np.resize(A, 1.0) # E: Argument 2 to "resize" has incompatible type
+
+np.squeeze(A, 1.0) # E: No overload variant of "squeeze" matches argument type
+
+np.diagonal(A, offset=None) # E: Argument "offset" to "diagonal" has incompatible type
+np.diagonal(A, axis1="bob") # E: Argument "axis1" to "diagonal" has incompatible type
+np.diagonal(A, axis2=[]) # E: Argument "axis2" to "diagonal" has incompatible type
+
+np.trace(A, offset=None) # E: Argument "offset" to "trace" has incompatible type
+np.trace(A, axis1="bob") # E: Argument "axis1" to "trace" has incompatible type
+np.trace(A, axis2=[]) # E: Argument "axis2" to "trace" has incompatible type
+
+np.ravel(a, order="bob") # E: Argument "order" to "ravel" has incompatible type
+
+np.compress(
+ [True], A, axis=1.0 # E: Argument "axis" to "compress" has incompatible type
+)
diff --git a/numpy/tests/typing/fail/ndarray.py b/numpy/tests/typing/fail/ndarray.py
new file mode 100644
index 000000000..5a5130d40
--- /dev/null
+++ b/numpy/tests/typing/fail/ndarray.py
@@ -0,0 +1,11 @@
+import numpy as np
+
+# Ban setting dtype since mutating the type of the array in place
+# makes having ndarray be generic over dtype impossible. Generally
+# users should use `ndarray.view` in this situation anyway. See
+#
+# https://github.com/numpy/numpy-stubs/issues/7
+#
+# for more context.
+float_array = np.array([1.0])
+float_array.dtype = np.bool_ # E: Property "dtype" defined in "ndarray" is read-only
diff --git a/numpy/tests/typing/fail/numerictypes.py b/numpy/tests/typing/fail/numerictypes.py
new file mode 100644
index 000000000..dd03eacc1
--- /dev/null
+++ b/numpy/tests/typing/fail/numerictypes.py
@@ -0,0 +1,13 @@
+import numpy as np
+
+# Techincally this works, but probably shouldn't. See
+#
+# https://github.com/numpy/numpy/issues/16366
+#
+np.maximum_sctype(1) # E: incompatible type "int"
+
+np.issubsctype(1, np.int64) # E: incompatible type "int"
+
+np.issubdtype(1, np.int64) # E: incompatible type "int"
+
+np.find_common_type(np.int64, np.int64) # E: incompatible type "Type[int64]"
diff --git a/numpy/tests/typing/fail/scalars.py b/numpy/tests/typing/fail/scalars.py
new file mode 100644
index 000000000..5d7221895
--- /dev/null
+++ b/numpy/tests/typing/fail/scalars.py
@@ -0,0 +1,81 @@
+import numpy as np
+
+# Construction
+
+np.float32(3j) # E: incompatible type
+
+# Technically the following examples are valid NumPy code. But they
+# are not considered a best practice, and people who wish to use the
+# stubs should instead do
+#
+# np.array([1.0, 0.0, 0.0], dtype=np.float32)
+# np.array([], dtype=np.complex64)
+#
+# See e.g. the discussion on the mailing list
+#
+# https://mail.python.org/pipermail/numpy-discussion/2020-April/080566.html
+#
+# and the issue
+#
+# https://github.com/numpy/numpy-stubs/issues/41
+#
+# for more context.
+np.float32([1.0, 0.0, 0.0]) # E: incompatible type
+np.complex64([]) # E: incompatible type
+
+np.complex64(1, 2) # E: Too many arguments
+# TODO: protocols (can't check for non-existent protocols w/ __getattr__)
+
+np.datetime64(0) # E: non-matching overload
+
+dt_64 = np.datetime64(0, "D")
+td_64 = np.timedelta64(1, "h")
+
+dt_64 + dt_64 # E: Unsupported operand types
+
+td_64 - dt_64 # E: Unsupported operand types
+td_64 / dt_64 # E: No overload
+td_64 % 1 # E: Unsupported operand types
+td_64 % dt_64 # E: Unsupported operand types
+
+
+class A:
+ def __float__(self):
+ return 1.0
+
+
+np.int8(A()) # E: incompatible type
+np.int16(A()) # E: incompatible type
+np.int32(A()) # E: incompatible type
+np.int64(A()) # E: incompatible type
+np.uint8(A()) # E: incompatible type
+np.uint16(A()) # E: incompatible type
+np.uint32(A()) # E: incompatible type
+np.uint64(A()) # E: incompatible type
+
+np.void("test") # E: incompatible type
+
+np.generic(1) # E: Cannot instantiate abstract class
+np.number(1) # E: Cannot instantiate abstract class
+np.integer(1) # E: Cannot instantiate abstract class
+np.signedinteger(1) # E: Cannot instantiate abstract class
+np.unsignedinteger(1) # E: Cannot instantiate abstract class
+np.inexact(1) # E: Cannot instantiate abstract class
+np.floating(1) # E: Cannot instantiate abstract class
+np.complexfloating(1) # E: Cannot instantiate abstract class
+np.character("test") # E: Cannot instantiate abstract class
+np.flexible(b"test") # E: Cannot instantiate abstract class
+
+np.float64(value=0.0) # E: Unexpected keyword argument
+np.int64(value=0) # E: Unexpected keyword argument
+np.uint64(value=0) # E: Unexpected keyword argument
+np.complex128(value=0.0j) # E: Unexpected keyword argument
+np.str_(value='bob') # E: No overload variant
+np.bytes_(value=b'test') # E: No overload variant
+np.void(value=b'test') # E: Unexpected keyword argument
+np.bool_(value=True) # E: Unexpected keyword argument
+np.datetime64(value="2019") # E: No overload variant
+np.timedelta64(value=0) # E: Unexpected keyword argument
+
+np.bytes_(b"hello", encoding='utf-8') # E: No overload variant
+np.str_("hello", encoding='utf-8') # E: No overload variant
diff --git a/numpy/tests/typing/fail/simple.py b/numpy/tests/typing/fail/simple.py
new file mode 100644
index 000000000..b5e9d1b13
--- /dev/null
+++ b/numpy/tests/typing/fail/simple.py
@@ -0,0 +1,10 @@
+"""Simple expression that should fail with mypy."""
+
+import numpy as np
+
+# Array creation routines checks
+np.zeros("test") # E: incompatible type
+np.zeros() # E: Too few arguments
+
+np.ones("test") # E: incompatible type
+np.ones() # E: Too few arguments
diff --git a/numpy/tests/typing/fail/ufuncs.py b/numpy/tests/typing/fail/ufuncs.py
new file mode 100644
index 000000000..b178a4ea4
--- /dev/null
+++ b/numpy/tests/typing/fail/ufuncs.py
@@ -0,0 +1,5 @@
+import numpy as np
+
+np.sin.nin + "foo" # E: Unsupported operand types
+np.sin(1, foo="bar") # E: Unexpected keyword argument
+np.sin(1, extobj=["foo", "foo", "foo"]) # E: incompatible type
diff --git a/numpy/tests/typing/fail/warnings_and_errors.py b/numpy/tests/typing/fail/warnings_and_errors.py
new file mode 100644
index 000000000..7390cc45f
--- /dev/null
+++ b/numpy/tests/typing/fail/warnings_and_errors.py
@@ -0,0 +1,7 @@
+import numpy as np
+
+np.AxisError(1.0) # E: Argument 1 to "AxisError" has incompatible type
+np.AxisError(1, ndim=2.0) # E: Argument "ndim" to "AxisError" has incompatible type
+np.AxisError(
+ 2, msg_prefix=404 # E: Argument "msg_prefix" to "AxisError" has incompatible type
+)
diff --git a/numpy/tests/typing/mypy.ini b/numpy/tests/typing/mypy.ini
new file mode 100644
index 000000000..91d93588a
--- /dev/null
+++ b/numpy/tests/typing/mypy.ini
@@ -0,0 +1,8 @@
+[mypy]
+mypy_path = ../../..
+
+[mypy-numpy]
+ignore_errors = True
+
+[mypy-numpy.*]
+ignore_errors = True
diff --git a/numpy/tests/typing/pass/array_like.py b/numpy/tests/typing/pass/array_like.py
new file mode 100644
index 000000000..098149c4b
--- /dev/null
+++ b/numpy/tests/typing/pass/array_like.py
@@ -0,0 +1,44 @@
+from typing import Any, List, Optional, TYPE_CHECKING
+
+import numpy as np
+
+if TYPE_CHECKING:
+ from numpy.typing import ArrayLike, DtypeLike, _SupportsArray
+else:
+ ArrayLike = Any
+ DtypeLike = Any
+ _SupportsArray = Any
+
+x1: ArrayLike = True
+x2: ArrayLike = 5
+x3: ArrayLike = 1.0
+x4: ArrayLike = 1 + 1j
+x5: ArrayLike = np.int8(1)
+x6: ArrayLike = np.float64(1)
+x7: ArrayLike = np.complex128(1)
+x8: ArrayLike = np.array([1, 2, 3])
+x9: ArrayLike = [1, 2, 3]
+x10: ArrayLike = (1, 2, 3)
+x11: ArrayLike = "foo"
+
+
+class A:
+ def __array__(self, dtype: DtypeLike = None) -> np.ndarray:
+ return np.array([1, 2, 3])
+
+
+x12: ArrayLike = A()
+
+scalar: _SupportsArray = np.int64(1)
+scalar.__array__(np.float64)
+array: _SupportsArray = np.array(1)
+array.__array__(np.float64)
+
+a: _SupportsArray = A()
+a.__array__(np.int64)
+a.__array__(dtype=np.int64)
+
+# Escape hatch for when you mean to make something like an object
+# array.
+object_array_scalar: Any = (i for i in range(10))
+np.array(object_array_scalar)
diff --git a/numpy/tests/typing/pass/dtype.py b/numpy/tests/typing/pass/dtype.py
new file mode 100644
index 000000000..f954fdd44
--- /dev/null
+++ b/numpy/tests/typing/pass/dtype.py
@@ -0,0 +1,3 @@
+import numpy as np
+
+np.dtype(dtype=np.int64)
diff --git a/numpy/tests/typing/pass/fromnumeric.py b/numpy/tests/typing/pass/fromnumeric.py
new file mode 100644
index 000000000..0ce8ef970
--- /dev/null
+++ b/numpy/tests/typing/pass/fromnumeric.py
@@ -0,0 +1,116 @@
+"""Tests for :mod:`numpy.core.fromnumeric`."""
+
+import numpy as np
+
+A = np.array(True, ndmin=2, dtype=bool)
+B = np.array(1.0, ndmin=2, dtype=np.float32)
+A.setflags(write=False)
+B.setflags(write=False)
+
+a = np.bool_(True)
+b = np.float32(1.0)
+c = 1.0
+
+np.take(a, 0)
+np.take(b, 0)
+np.take(c, 0)
+np.take(A, 0)
+np.take(B, 0)
+np.take(A, [0])
+np.take(B, [0])
+
+np.reshape(a, 1)
+np.reshape(b, 1)
+np.reshape(c, 1)
+np.reshape(A, 1)
+np.reshape(B, 1)
+
+np.choose(a, [True, True])
+np.choose(A, [1.0, 1.0])
+
+np.repeat(a, 1)
+np.repeat(b, 1)
+np.repeat(c, 1)
+np.repeat(A, 1)
+np.repeat(B, 1)
+
+np.swapaxes(A, 0, 0)
+np.swapaxes(B, 0, 0)
+
+np.transpose(a)
+np.transpose(b)
+np.transpose(c)
+np.transpose(A)
+np.transpose(B)
+
+np.partition(a, 0, axis=None)
+np.partition(b, 0, axis=None)
+np.partition(c, 0, axis=None)
+np.partition(A, 0)
+np.partition(B, 0)
+
+np.argpartition(a, 0)
+np.argpartition(b, 0)
+np.argpartition(c, 0)
+np.argpartition(A, 0)
+np.argpartition(B, 0)
+
+np.sort(A, 0)
+np.sort(B, 0)
+
+np.argsort(A, 0)
+np.argsort(B, 0)
+
+np.argmax(A)
+np.argmax(B)
+np.argmax(A, axis=0)
+np.argmax(B, axis=0)
+
+np.argmin(A)
+np.argmin(B)
+np.argmin(A, axis=0)
+np.argmin(B, axis=0)
+
+np.searchsorted(A[0], 0)
+np.searchsorted(B[0], 0)
+np.searchsorted(A[0], [0])
+np.searchsorted(B[0], [0])
+
+np.resize(a, (5, 5))
+np.resize(b, (5, 5))
+np.resize(c, (5, 5))
+np.resize(A, (5, 5))
+np.resize(B, (5, 5))
+
+np.squeeze(a)
+np.squeeze(b)
+np.squeeze(c)
+np.squeeze(A)
+np.squeeze(B)
+
+np.diagonal(A)
+np.diagonal(B)
+
+np.trace(A)
+np.trace(B)
+
+np.ravel(a)
+np.ravel(b)
+np.ravel(c)
+np.ravel(A)
+np.ravel(B)
+
+np.nonzero(A)
+np.nonzero(B)
+
+np.shape(a)
+np.shape(b)
+np.shape(c)
+np.shape(A)
+np.shape(B)
+
+np.compress([True], a)
+np.compress([True], b)
+np.compress([True], c)
+np.compress([True], A)
+np.compress([True], B)
diff --git a/numpy/tests/typing/pass/ndarray_conversion.py b/numpy/tests/typing/pass/ndarray_conversion.py
new file mode 100644
index 000000000..303cf53e4
--- /dev/null
+++ b/numpy/tests/typing/pass/ndarray_conversion.py
@@ -0,0 +1,94 @@
+import os
+import tempfile
+
+import numpy as np
+
+nd = np.array([[1, 2], [3, 4]])
+scalar_array = np.array(1)
+
+# item
+scalar_array.item()
+nd.item(1)
+nd.item(0, 1)
+nd.item((0, 1))
+
+# tolist is pretty simple
+
+# itemset
+scalar_array.itemset(3)
+nd.itemset(3, 0)
+nd.itemset((0, 0), 3)
+
+# tobytes
+nd.tobytes()
+nd.tobytes("C")
+nd.tobytes(None)
+
+# tofile
+if os.name != "nt":
+ with tempfile.NamedTemporaryFile(suffix=".txt") as tmp:
+ nd.tofile(tmp.name)
+ nd.tofile(tmp.name, "")
+ nd.tofile(tmp.name, sep="")
+
+ nd.tofile(tmp.name, "", "%s")
+ nd.tofile(tmp.name, format="%s")
+
+ nd.tofile(tmp)
+
+# dump is pretty simple
+# dumps is pretty simple
+
+# astype
+nd.astype("float")
+nd.astype(float)
+
+nd.astype(float, "K")
+nd.astype(float, order="K")
+
+nd.astype(float, "K", "unsafe")
+nd.astype(float, casting="unsafe")
+
+nd.astype(float, "K", "unsafe", True)
+nd.astype(float, subok=True)
+
+nd.astype(float, "K", "unsafe", True, True)
+nd.astype(float, copy=True)
+
+# byteswap
+nd.byteswap()
+nd.byteswap(True)
+
+# copy
+nd.copy()
+nd.copy("C")
+
+# view
+nd.view()
+nd.view(np.int64)
+nd.view(dtype=np.int64)
+nd.view(np.int64, np.matrix)
+nd.view(type=np.matrix)
+
+# getfield
+complex_array = np.array([[1 + 1j, 0], [0, 1 - 1j]], dtype=np.complex128)
+
+complex_array.getfield("float")
+complex_array.getfield(float)
+
+complex_array.getfield("float", 8)
+complex_array.getfield(float, offset=8)
+
+# setflags
+nd.setflags()
+
+nd.setflags(True)
+nd.setflags(write=True)
+
+nd.setflags(True, True)
+nd.setflags(write=True, align=True)
+
+nd.setflags(True, True, False)
+nd.setflags(write=True, align=True, uic=False)
+
+# fill is pretty simple
diff --git a/numpy/tests/typing/pass/ndarray_shape_manipulation.py b/numpy/tests/typing/pass/ndarray_shape_manipulation.py
new file mode 100644
index 000000000..0ca3dff39
--- /dev/null
+++ b/numpy/tests/typing/pass/ndarray_shape_manipulation.py
@@ -0,0 +1,47 @@
+import numpy as np
+
+nd1 = np.array([[1, 2], [3, 4]])
+
+# reshape
+nd1.reshape(4)
+nd1.reshape(2, 2)
+nd1.reshape((2, 2))
+
+nd1.reshape((2, 2), order="C")
+nd1.reshape(4, order="C")
+
+# resize
+nd1.resize()
+nd1.resize(4)
+nd1.resize(2, 2)
+nd1.resize((2, 2))
+
+nd1.resize((2, 2), refcheck=True)
+nd1.resize(4, refcheck=True)
+
+nd2 = np.array([[1, 2], [3, 4]])
+
+# transpose
+nd2.transpose()
+nd2.transpose(1, 0)
+nd2.transpose((1, 0))
+
+# swapaxes
+nd2.swapaxes(0, 1)
+
+# flatten
+nd2.flatten()
+nd2.flatten("C")
+
+# ravel
+nd2.ravel()
+nd2.ravel("C")
+
+# squeeze
+nd2.squeeze()
+
+nd3 = np.array([[1, 2]])
+nd3.squeeze(0)
+
+nd4 = np.array([[[1, 2]]])
+nd4.squeeze((0, 1))
diff --git a/numpy/tests/typing/pass/numerictypes.py b/numpy/tests/typing/pass/numerictypes.py
new file mode 100644
index 000000000..4f205cabc
--- /dev/null
+++ b/numpy/tests/typing/pass/numerictypes.py
@@ -0,0 +1,29 @@
+import numpy as np
+
+np.maximum_sctype("S8")
+np.maximum_sctype(object)
+
+np.issctype(object)
+np.issctype("S8")
+
+np.obj2sctype(list)
+np.obj2sctype(list, default=None)
+np.obj2sctype(list, default=np.string_)
+
+np.issubclass_(np.int32, int)
+np.issubclass_(np.float64, float)
+np.issubclass_(np.float64, (int, float))
+
+np.issubsctype("int64", int)
+np.issubsctype(np.array([1]), np.array([1]))
+
+np.issubdtype("S1", np.string_)
+np.issubdtype(np.float64, np.float32)
+
+np.sctype2char("S1")
+np.sctype2char(list)
+
+np.find_common_type([], [np.int64, np.float32, complex])
+np.find_common_type((), (np.int64, np.float32, complex))
+np.find_common_type([np.int64, np.float32], [])
+np.find_common_type([np.float32], [np.int64, np.float64])
diff --git a/numpy/tests/typing/pass/scalars.py b/numpy/tests/typing/pass/scalars.py
new file mode 100644
index 000000000..7de182626
--- /dev/null
+++ b/numpy/tests/typing/pass/scalars.py
@@ -0,0 +1,92 @@
+import numpy as np
+
+
+# Construction
+class C:
+ def __complex__(self):
+ return 3j
+
+
+class B:
+ def __int__(self):
+ return 4
+
+
+class A:
+ def __float__(self):
+ return 4.0
+
+
+np.complex64(3j)
+np.complex64(C())
+np.complex128(3j)
+np.complex128(C())
+
+np.int8(4)
+np.int16(3.4)
+np.int32(4)
+np.int64(-1)
+np.uint8(B())
+np.uint32()
+
+np.float16(A())
+np.float32(16)
+np.float64(3.0)
+
+np.bytes_(b"hello")
+np.bytes_("hello", 'utf-8')
+np.bytes_("hello", encoding='utf-8')
+np.str_("hello")
+np.str_(b"hello", 'utf-8')
+np.str_(b"hello", encoding='utf-8')
+
+# Protocols
+float(np.int8(4))
+int(np.int16(5))
+np.int8(np.float32(6))
+
+# TODO(alan): test after https://github.com/python/typeshed/pull/2004
+# complex(np.int32(8))
+
+abs(np.int8(4))
+
+# Array-ish semantics
+np.int8().real
+np.int16().imag
+np.int32().data
+np.int64().flags
+
+np.uint8().itemsize * 2
+np.uint16().ndim + 1
+np.uint32().strides
+np.uint64().shape
+
+# Time structures
+np.datetime64()
+np.datetime64(0, "D")
+np.datetime64("2019")
+np.datetime64("2019", "D")
+
+np.timedelta64()
+np.timedelta64(0)
+np.timedelta64(0, "D")
+
+dt_64 = np.datetime64(0, "D")
+td_64 = np.timedelta64(1, "h")
+
+dt_64 + td_64
+dt_64 - dt_64
+dt_64 - td_64
+
+td_64 + td_64
+td_64 - td_64
+td_64 / 1.0
+td_64 / td_64
+td_64 % td_64
+
+np.void(1)
+np.void(np.int64(1))
+np.void(True)
+np.void(np.bool_(True))
+np.void(b"test")
+np.void(np.bytes_("test"))
diff --git a/numpy/tests/typing/pass/simple.py b/numpy/tests/typing/pass/simple.py
new file mode 100644
index 000000000..e0157ab81
--- /dev/null
+++ b/numpy/tests/typing/pass/simple.py
@@ -0,0 +1,176 @@
+"""Simple expression that should pass with mypy."""
+import operator
+
+import numpy as np
+from typing import Iterable # noqa: F401
+
+# Basic checks
+array = np.array([1, 2])
+
+
+def ndarray_func(x):
+ # type: (np.ndarray) -> np.ndarray
+ return x
+
+
+ndarray_func(np.array([1, 2]))
+array == 1
+array.dtype == float
+
+# Array creation routines checks
+ndarray_func(np.zeros([1, 2]))
+ndarray_func(np.ones([1, 2]))
+ndarray_func(np.empty([1, 2]))
+
+ndarray_func(np.zeros_like(array))
+ndarray_func(np.ones_like(array))
+ndarray_func(np.empty_like(array))
+
+# Dtype construction
+np.dtype(float)
+np.dtype(np.float64)
+np.dtype(None)
+np.dtype("float64")
+np.dtype(np.dtype(float))
+np.dtype(("U", 10))
+np.dtype((np.int32, (2, 2)))
+# Define the arguments on the previous line to prevent bidirectional
+# type inference in mypy from broadening the types.
+two_tuples_dtype = [("R", "u1"), ("G", "u1"), ("B", "u1")]
+np.dtype(two_tuples_dtype)
+
+three_tuples_dtype = [("R", "u1", 2)]
+np.dtype(three_tuples_dtype)
+
+mixed_tuples_dtype = [("R", "u1"), ("G", np.unicode_, 1)]
+np.dtype(mixed_tuples_dtype)
+
+shape_tuple_dtype = [("R", "u1", (2, 2))]
+np.dtype(shape_tuple_dtype)
+
+shape_like_dtype = [("R", "u1", (2, 2)), ("G", np.unicode_, 1)]
+np.dtype(shape_like_dtype)
+
+object_dtype = [("field1", object)]
+np.dtype(object_dtype)
+
+np.dtype({"col1": ("U10", 0), "col2": ("float32", 10)})
+np.dtype((np.int32, {"real": (np.int16, 0), "imag": (np.int16, 2)}))
+np.dtype((np.int32, (np.int8, 4)))
+
+# Dtype comparision
+np.dtype(float) == float
+np.dtype(float) != np.float64
+np.dtype(float) < None
+np.dtype(float) <= "float64"
+np.dtype(float) > np.dtype(float)
+np.dtype(float) >= np.dtype(("U", 10))
+
+# Iteration and indexing
+def iterable_func(x):
+ # type: (Iterable) -> Iterable
+ return x
+
+
+iterable_func(array)
+[element for element in array]
+iter(array)
+zip(array, array)
+array[1]
+array[:]
+array[...]
+array[:] = 0
+
+array_2d = np.ones((3, 3))
+array_2d[:2, :2]
+array_2d[..., 0]
+array_2d[:2, :2] = 0
+
+# Other special methods
+len(array)
+str(array)
+array_scalar = np.array(1)
+int(array_scalar)
+float(array_scalar)
+# currently does not work due to https://github.com/python/typeshed/issues/1904
+# complex(array_scalar)
+bytes(array_scalar)
+operator.index(array_scalar)
+bool(array_scalar)
+
+# comparisons
+array < 1
+array <= 1
+array == 1
+array != 1
+array > 1
+array >= 1
+1 < array
+1 <= array
+1 == array
+1 != array
+1 > array
+1 >= array
+
+# binary arithmetic
+array + 1
+1 + array
+array += 1
+
+array - 1
+1 - array
+array -= 1
+
+array * 1
+1 * array
+array *= 1
+
+nonzero_array = np.array([1, 2])
+array / 1
+1 / nonzero_array
+float_array = np.array([1.0, 2.0])
+float_array /= 1
+
+array // 1
+1 // nonzero_array
+array //= 1
+
+array % 1
+1 % nonzero_array
+array %= 1
+
+divmod(array, 1)
+divmod(1, nonzero_array)
+
+array ** 1
+1 ** array
+array **= 1
+
+array << 1
+1 << array
+array <<= 1
+
+array >> 1
+1 >> array
+array >>= 1
+
+array & 1
+1 & array
+array &= 1
+
+array ^ 1
+1 ^ array
+array ^= 1
+
+array | 1
+1 | array
+array |= 1
+
+# unary arithmetic
+-array
++array
+abs(array)
+~array
+
+# Other methods
+np.array([1, 2]).transpose()
diff --git a/numpy/tests/typing/pass/simple_py3.py b/numpy/tests/typing/pass/simple_py3.py
new file mode 100644
index 000000000..c05a1ce61
--- /dev/null
+++ b/numpy/tests/typing/pass/simple_py3.py
@@ -0,0 +1,6 @@
+import numpy as np
+
+array = np.array([1, 2])
+
+# The @ operator is not in python 2
+array @ array
diff --git a/numpy/tests/typing/pass/ufuncs.py b/numpy/tests/typing/pass/ufuncs.py
new file mode 100644
index 000000000..c81ac48d1
--- /dev/null
+++ b/numpy/tests/typing/pass/ufuncs.py
@@ -0,0 +1,11 @@
+import numpy as np
+
+np.sin(1)
+np.sin([1, 2, 3])
+np.sin(1, out=np.empty(1))
+np.matmul(np.ones((2, 2, 2)), np.ones((2, 2, 2)), axes=[(0, 1), (0, 1), (0, 1)])
+np.sin(1, signature="D")
+np.sin(1, extobj=[16, 1, lambda: None])
+np.sin(1) + np.sin(1)
+np.sin.types[0]
+np.sin.__name__
diff --git a/numpy/tests/typing/pass/warnings_and_errors.py b/numpy/tests/typing/pass/warnings_and_errors.py
new file mode 100644
index 000000000..5b6ec2626
--- /dev/null
+++ b/numpy/tests/typing/pass/warnings_and_errors.py
@@ -0,0 +1,7 @@
+import numpy as np
+
+np.AxisError(1)
+np.AxisError(1, ndim=2)
+np.AxisError(1, ndim=None)
+np.AxisError(1, ndim=2, msg_prefix="error")
+np.AxisError(1, ndim=2, msg_prefix=None)
diff --git a/numpy/tests/typing/reveal/constants.py b/numpy/tests/typing/reveal/constants.py
new file mode 100644
index 000000000..8e00810bd
--- /dev/null
+++ b/numpy/tests/typing/reveal/constants.py
@@ -0,0 +1,44 @@
+import numpy as np
+
+reveal_type(np.Inf) # E: float
+reveal_type(np.Infinity) # E: float
+reveal_type(np.NAN) # E: float
+reveal_type(np.NINF) # E: float
+reveal_type(np.NZERO) # E: float
+reveal_type(np.NaN) # E: float
+reveal_type(np.PINF) # E: float
+reveal_type(np.PZERO) # E: float
+reveal_type(np.e) # E: float
+reveal_type(np.euler_gamma) # E: float
+reveal_type(np.inf) # E: float
+reveal_type(np.infty) # E: float
+reveal_type(np.nan) # E: float
+reveal_type(np.pi) # E: float
+
+reveal_type(np.ALLOW_THREADS) # E: int
+reveal_type(np.BUFSIZE) # E: int
+reveal_type(np.CLIP) # E: int
+reveal_type(np.ERR_CALL) # E: int
+reveal_type(np.ERR_DEFAULT) # E: int
+reveal_type(np.ERR_IGNORE) # E: int
+reveal_type(np.ERR_LOG) # E: int
+reveal_type(np.ERR_PRINT) # E: int
+reveal_type(np.ERR_RAISE) # E: int
+reveal_type(np.ERR_WARN) # E: int
+reveal_type(np.FLOATING_POINT_SUPPORT) # E: int
+reveal_type(np.FPE_DIVIDEBYZERO) # E: int
+reveal_type(np.FPE_INVALID) # E: int
+reveal_type(np.FPE_OVERFLOW) # E: int
+reveal_type(np.FPE_UNDERFLOW) # E: int
+reveal_type(np.MAXDIMS) # E: int
+reveal_type(np.MAY_SHARE_BOUNDS) # E: int
+reveal_type(np.MAY_SHARE_EXACT) # E: int
+reveal_type(np.RAISE) # E: int
+reveal_type(np.SHIFT_DIVIDEBYZERO) # E: int
+reveal_type(np.SHIFT_INVALID) # E: int
+reveal_type(np.SHIFT_OVERFLOW) # E: int
+reveal_type(np.SHIFT_UNDERFLOW) # E: int
+reveal_type(np.UFUNC_BUFSIZE_DEFAULT) # E: int
+reveal_type(np.WRAP) # E: int
+reveal_type(np.little_endian) # E: int
+reveal_type(np.tracemalloc_domain) # E: int
diff --git a/numpy/tests/typing/reveal/fromnumeric.py b/numpy/tests/typing/reveal/fromnumeric.py
new file mode 100644
index 000000000..7d79d5fa9
--- /dev/null
+++ b/numpy/tests/typing/reveal/fromnumeric.py
@@ -0,0 +1,135 @@
+"""Tests for :mod:`numpy.core.fromnumeric`."""
+
+import numpy as np
+
+A = np.array(True, ndmin=2, dtype=bool)
+B = np.array(1.0, ndmin=2, dtype=np.float32)
+A.setflags(write=False)
+B.setflags(write=False)
+
+a = np.bool_(True)
+b = np.float32(1.0)
+c = 1.0
+
+reveal_type(np.take(a, 0)) # E: numpy.bool_
+reveal_type(np.take(b, 0)) # E: numpy.float32
+reveal_type(
+ np.take(c, 0) # E: Union[numpy.generic, datetime.datetime, datetime.timedelta]
+)
+reveal_type(
+ np.take(A, 0) # E: Union[numpy.generic, datetime.datetime, datetime.timedelta]
+)
+reveal_type(
+ np.take(B, 0) # E: Union[numpy.generic, datetime.datetime, datetime.timedelta]
+)
+reveal_type(
+ np.take( # E: Union[Union[numpy.generic, datetime.datetime, datetime.timedelta], numpy.ndarray]
+ A, [0]
+ )
+)
+reveal_type(
+ np.take( # E: Union[Union[numpy.generic, datetime.datetime, datetime.timedelta], numpy.ndarray]
+ B, [0]
+ )
+)
+
+reveal_type(np.reshape(a, 1)) # E: numpy.ndarray
+reveal_type(np.reshape(b, 1)) # E: numpy.ndarray
+reveal_type(np.reshape(c, 1)) # E: numpy.ndarray
+reveal_type(np.reshape(A, 1)) # E: numpy.ndarray
+reveal_type(np.reshape(B, 1)) # E: numpy.ndarray
+
+reveal_type(np.choose(a, [True, True])) # E: numpy.bool_
+reveal_type(np.choose(A, [True, True])) # E: numpy.ndarray
+
+reveal_type(np.repeat(a, 1)) # E: numpy.ndarray
+reveal_type(np.repeat(b, 1)) # E: numpy.ndarray
+reveal_type(np.repeat(c, 1)) # E: numpy.ndarray
+reveal_type(np.repeat(A, 1)) # E: numpy.ndarray
+reveal_type(np.repeat(B, 1)) # E: numpy.ndarray
+
+# TODO: Add tests for np.put()
+
+reveal_type(np.swapaxes(A, 0, 0)) # E: numpy.ndarray
+reveal_type(np.swapaxes(B, 0, 0)) # E: numpy.ndarray
+
+reveal_type(np.transpose(a)) # E: numpy.ndarray
+reveal_type(np.transpose(b)) # E: numpy.ndarray
+reveal_type(np.transpose(c)) # E: numpy.ndarray
+reveal_type(np.transpose(A)) # E: numpy.ndarray
+reveal_type(np.transpose(B)) # E: numpy.ndarray
+
+reveal_type(np.partition(a, 0, axis=None)) # E: numpy.ndarray
+reveal_type(np.partition(b, 0, axis=None)) # E: numpy.ndarray
+reveal_type(np.partition(c, 0, axis=None)) # E: numpy.ndarray
+reveal_type(np.partition(A, 0)) # E: numpy.ndarray
+reveal_type(np.partition(B, 0)) # E: numpy.ndarray
+
+reveal_type(np.argpartition(a, 0)) # E: numpy.integer
+reveal_type(np.argpartition(b, 0)) # E: numpy.integer
+reveal_type(np.argpartition(c, 0)) # E: numpy.ndarray
+reveal_type(np.argpartition(A, 0)) # E: numpy.ndarray
+reveal_type(np.argpartition(B, 0)) # E: numpy.ndarray
+
+reveal_type(np.sort(A, 0)) # E: numpy.ndarray
+reveal_type(np.sort(B, 0)) # E: numpy.ndarray
+
+reveal_type(np.argsort(A, 0)) # E: numpy.ndarray
+reveal_type(np.argsort(B, 0)) # E: numpy.ndarray
+
+reveal_type(np.argmax(A)) # E: numpy.integer
+reveal_type(np.argmax(B)) # E: numpy.integer
+reveal_type(np.argmax(A, axis=0)) # E: Union[numpy.integer, numpy.ndarray]
+reveal_type(np.argmax(B, axis=0)) # E: Union[numpy.integer, numpy.ndarray]
+
+reveal_type(np.argmin(A)) # E: numpy.integer
+reveal_type(np.argmin(B)) # E: numpy.integer
+reveal_type(np.argmin(A, axis=0)) # E: Union[numpy.integer, numpy.ndarray]
+reveal_type(np.argmin(B, axis=0)) # E: Union[numpy.integer, numpy.ndarray]
+
+reveal_type(np.searchsorted(A[0], 0)) # E: numpy.integer
+reveal_type(np.searchsorted(B[0], 0)) # E: numpy.integer
+reveal_type(np.searchsorted(A[0], [0])) # E: numpy.ndarray
+reveal_type(np.searchsorted(B[0], [0])) # E: numpy.ndarray
+
+reveal_type(np.resize(a, (5, 5))) # E: numpy.ndarray
+reveal_type(np.resize(b, (5, 5))) # E: numpy.ndarray
+reveal_type(np.resize(c, (5, 5))) # E: numpy.ndarray
+reveal_type(np.resize(A, (5, 5))) # E: numpy.ndarray
+reveal_type(np.resize(B, (5, 5))) # E: numpy.ndarray
+
+reveal_type(np.squeeze(a)) # E: numpy.bool_
+reveal_type(np.squeeze(b)) # E: numpy.float32
+reveal_type(np.squeeze(c)) # E: numpy.ndarray
+reveal_type(np.squeeze(A)) # E: numpy.ndarray
+reveal_type(np.squeeze(B)) # E: numpy.ndarray
+
+reveal_type(np.diagonal(A)) # E: numpy.ndarray
+reveal_type(np.diagonal(B)) # E: numpy.ndarray
+
+reveal_type(np.trace(A)) # E: Union[numpy.number, numpy.ndarray]
+reveal_type(np.trace(B)) # E: Union[numpy.number, numpy.ndarray]
+
+reveal_type(np.ravel(a)) # E: numpy.ndarray
+reveal_type(np.ravel(b)) # E: numpy.ndarray
+reveal_type(np.ravel(c)) # E: numpy.ndarray
+reveal_type(np.ravel(A)) # E: numpy.ndarray
+reveal_type(np.ravel(B)) # E: numpy.ndarray
+
+reveal_type(np.nonzero(a)) # E: tuple[numpy.ndarray]
+reveal_type(np.nonzero(b)) # E: tuple[numpy.ndarray]
+reveal_type(np.nonzero(c)) # E: tuple[numpy.ndarray]
+reveal_type(np.nonzero(A)) # E: tuple[numpy.ndarray]
+reveal_type(np.nonzero(B)) # E: tuple[numpy.ndarray]
+
+reveal_type(np.shape(a)) # E: tuple[builtins.int]
+reveal_type(np.shape(b)) # E: tuple[builtins.int]
+reveal_type(np.shape(c)) # E: tuple[builtins.int]
+reveal_type(np.shape(A)) # E: tuple[builtins.int]
+reveal_type(np.shape(B)) # E: tuple[builtins.int]
+
+reveal_type(np.compress([True], a)) # E: numpy.ndarray
+reveal_type(np.compress([True], b)) # E: numpy.ndarray
+reveal_type(np.compress([True], c)) # E: numpy.ndarray
+reveal_type(np.compress([True], A)) # E: numpy.ndarray
+reveal_type(np.compress([True], B)) # E: numpy.ndarray
diff --git a/numpy/tests/typing/reveal/ndarray_conversion.py b/numpy/tests/typing/reveal/ndarray_conversion.py
new file mode 100644
index 000000000..411adcf63
--- /dev/null
+++ b/numpy/tests/typing/reveal/ndarray_conversion.py
@@ -0,0 +1,54 @@
+import numpy as np
+
+nd = np.array([[1, 2], [3, 4]])
+
+# item
+reveal_type(nd.item()) # E: Any
+reveal_type(nd.item(1)) # E: Any
+reveal_type(nd.item(0, 1)) # E: Any
+reveal_type(nd.item((0, 1))) # E: Any
+
+# tolist
+reveal_type(nd.tolist()) # E: builtins.list[Any]
+
+# itemset does not return a value
+# tostring is pretty simple
+# tobytes is pretty simple
+# tofile does not return a value
+# dump does not return a value
+# dumps is pretty simple
+
+# astype
+reveal_type(nd.astype("float")) # E: numpy.ndarray
+reveal_type(nd.astype(float)) # E: numpy.ndarray
+reveal_type(nd.astype(float, "K")) # E: numpy.ndarray
+reveal_type(nd.astype(float, "K", "unsafe")) # E: numpy.ndarray
+reveal_type(nd.astype(float, "K", "unsafe", True)) # E: numpy.ndarray
+reveal_type(nd.astype(float, "K", "unsafe", True, True)) # E: numpy.ndarray
+
+# byteswap
+reveal_type(nd.byteswap()) # E: numpy.ndarray
+reveal_type(nd.byteswap(True)) # E: numpy.ndarray
+
+# copy
+reveal_type(nd.copy()) # E: numpy.ndarray
+reveal_type(nd.copy("C")) # E: numpy.ndarray
+
+# view
+class SubArray(np.ndarray):
+ pass
+
+
+reveal_type(nd.view()) # E: numpy.ndarray
+reveal_type(nd.view(np.int64)) # E: numpy.ndarray
+# replace `Any` with `numpy.matrix` when `matrix` will be added to stubs
+reveal_type(nd.view(np.int64, np.matrix)) # E: Any
+reveal_type(nd.view(np.int64, SubArray)) # E: SubArray
+
+# getfield
+reveal_type(nd.getfield("float")) # E: numpy.ndarray
+reveal_type(nd.getfield(float)) # E: numpy.ndarray
+reveal_type(nd.getfield(float, 8)) # E: numpy.ndarray
+
+# setflags does not return a value
+# fill does not return a value
diff --git a/numpy/tests/typing/reveal/ndarray_shape_manipulation.py b/numpy/tests/typing/reveal/ndarray_shape_manipulation.py
new file mode 100644
index 000000000..a44e1cfa1
--- /dev/null
+++ b/numpy/tests/typing/reveal/ndarray_shape_manipulation.py
@@ -0,0 +1,35 @@
+import numpy as np
+
+nd = np.array([[1, 2], [3, 4]])
+
+# reshape
+reveal_type(nd.reshape()) # E: numpy.ndarray
+reveal_type(nd.reshape(4)) # E: numpy.ndarray
+reveal_type(nd.reshape(2, 2)) # E: numpy.ndarray
+reveal_type(nd.reshape((2, 2))) # E: numpy.ndarray
+
+reveal_type(nd.reshape((2, 2), order="C")) # E: numpy.ndarray
+reveal_type(nd.reshape(4, order="C")) # E: numpy.ndarray
+
+# resize does not return a value
+
+# transpose
+reveal_type(nd.transpose()) # E: numpy.ndarray
+reveal_type(nd.transpose(1, 0)) # E: numpy.ndarray
+reveal_type(nd.transpose((1, 0))) # E: numpy.ndarray
+
+# swapaxes
+reveal_type(nd.swapaxes(0, 1)) # E: numpy.ndarray
+
+# flatten
+reveal_type(nd.flatten()) # E: numpy.ndarray
+reveal_type(nd.flatten("C")) # E: numpy.ndarray
+
+# ravel
+reveal_type(nd.ravel()) # E: numpy.ndarray
+reveal_type(nd.ravel("C")) # E: numpy.ndarray
+
+# squeeze
+reveal_type(nd.squeeze()) # E: numpy.ndarray
+reveal_type(nd.squeeze(0)) # E: numpy.ndarray
+reveal_type(nd.squeeze((0, 2))) # E: numpy.ndarray
diff --git a/numpy/tests/typing/reveal/numerictypes.py b/numpy/tests/typing/reveal/numerictypes.py
new file mode 100644
index 000000000..e026158cd
--- /dev/null
+++ b/numpy/tests/typing/reveal/numerictypes.py
@@ -0,0 +1,18 @@
+import numpy as np
+
+reveal_type(np.issctype(np.generic)) # E: bool
+reveal_type(np.issctype("foo")) # E: bool
+
+reveal_type(np.obj2sctype("S8")) # E: Union[numpy.generic, None]
+reveal_type(np.obj2sctype("S8", default=None)) # E: Union[numpy.generic, None]
+reveal_type(
+ np.obj2sctype("foo", default=int) # E: Union[numpy.generic, Type[builtins.int*]]
+)
+
+reveal_type(np.issubclass_(np.float64, float)) # E: bool
+reveal_type(np.issubclass_(np.float64, (int, float))) # E: bool
+
+reveal_type(np.sctype2char("S8")) # E: str
+reveal_type(np.sctype2char(list)) # E: str
+
+reveal_type(np.find_common_type([np.int64], [np.int64])) # E: numpy.dtype
diff --git a/numpy/tests/typing/reveal/scalars.py b/numpy/tests/typing/reveal/scalars.py
new file mode 100644
index 000000000..8a9555fc3
--- /dev/null
+++ b/numpy/tests/typing/reveal/scalars.py
@@ -0,0 +1,30 @@
+import numpy as np
+
+x = np.complex64(3 + 2j)
+
+reveal_type(x.real) # E: numpy.float32
+reveal_type(x.imag) # E: numpy.float32
+
+reveal_type(x.real.real) # E: numpy.float32
+reveal_type(x.real.imag) # E: numpy.float32
+
+reveal_type(x.itemsize) # E: int
+reveal_type(x.shape) # E: tuple[builtins.int]
+reveal_type(x.strides) # E: tuple[builtins.int]
+
+# Time structures
+dt = np.datetime64(0, "D")
+td = np.timedelta64(0, "D")
+
+reveal_type(dt + td) # E: numpy.datetime64
+reveal_type(dt + 1) # E: numpy.datetime64
+reveal_type(dt - dt) # E: numpy.timedelta64
+reveal_type(dt - 1) # E: numpy.timedelta64
+
+reveal_type(td + td) # E: numpy.timedelta64
+reveal_type(td + 1) # E: numpy.timedelta64
+reveal_type(td - td) # E: numpy.timedelta64
+reveal_type(td - 1) # E: numpy.timedelta64
+reveal_type(td / 1.0) # E: numpy.timedelta64
+reveal_type(td / td) # E: float
+reveal_type(td % td) # E: numpy.timedelta64
diff --git a/numpy/tests/typing/reveal/warnings_and_errors.py b/numpy/tests/typing/reveal/warnings_and_errors.py
new file mode 100644
index 000000000..c428deb7a
--- /dev/null
+++ b/numpy/tests/typing/reveal/warnings_and_errors.py
@@ -0,0 +1,10 @@
+from typing import Type
+
+import numpy as np
+
+reveal_type(np.ModuleDeprecationWarning()) # E: numpy.ModuleDeprecationWarning
+reveal_type(np.VisibleDeprecationWarning()) # E: numpy.VisibleDeprecationWarning
+reveal_type(np.ComplexWarning()) # E: numpy.ComplexWarning
+reveal_type(np.RankWarning()) # E: numpy.RankWarning
+reveal_type(np.TooHardError()) # E: numpy.TooHardError
+reveal_type(np.AxisError(1)) # E: numpy.AxisError
diff --git a/numpy/typing.pyi b/numpy/typing.pyi
new file mode 100644
index 000000000..f5705192a
--- /dev/null
+++ b/numpy/typing.pyi
@@ -0,0 +1,64 @@
+import sys
+from typing import Any, Dict, List, overload, Sequence, Text, Tuple, Union
+
+from numpy import dtype, ndarray
+
+if sys.version_info >= (3, 8):
+ from typing import Protocol
+else:
+ from typing_extensions import Protocol
+
+_Shape = Tuple[int, ...]
+
+# Anything that can be coerced to a shape tuple
+_ShapeLike = Union[int, Sequence[int]]
+
+_DtypeLikeNested = Any # TODO: wait for support for recursive types
+
+# Anything that can be coerced into numpy.dtype.
+# Reference: https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html
+DtypeLike = Union[
+ dtype,
+ # default data type (float64)
+ None,
+ # array-scalar types and generic types
+ type, # TODO: enumerate these when we add type hints for numpy scalars
+ # TODO: add a protocol for anything with a dtype attribute
+ # character codes, type strings or comma-separated fields, e.g., 'float64'
+ str,
+ # (flexible_dtype, itemsize)
+ Tuple[_DtypeLikeNested, int],
+ # (fixed_dtype, shape)
+ Tuple[_DtypeLikeNested, _ShapeLike],
+ # [(field_name, field_dtype, field_shape), ...]
+ #
+ # The type here is quite broad because NumPy accepts quite a wide
+ # range of inputs inside the list; see the tests for some
+ # examples.
+ List[Any],
+ # {'names': ..., 'formats': ..., 'offsets': ..., 'titles': ...,
+ # 'itemsize': ...}
+ # TODO: use TypedDict when/if it's officially supported
+ Dict[
+ str,
+ Union[
+ Sequence[str], # names
+ Sequence[_DtypeLikeNested], # formats
+ Sequence[int], # offsets
+ Sequence[Union[bytes, Text, None]], # titles
+ int, # itemsize
+ ],
+ ],
+ # {'field1': ..., 'field2': ..., ...}
+ Dict[str, Tuple[_DtypeLikeNested, int]],
+ # (base_dtype, new_dtype)
+ Tuple[_DtypeLikeNested, _DtypeLikeNested],
+]
+
+class _SupportsArray(Protocol):
+ @overload
+ def __array__(self, __dtype: DtypeLike = ...) -> ndarray: ...
+ @overload
+ def __array__(self, dtype: DtypeLike = ...) -> ndarray: ...
+
+ArrayLike = Union[bool, int, float, complex, _SupportsArray, Sequence]
diff --git a/site.cfg.example b/site.cfg.example
index 3eba3bbd7..c809303a2 100644
--- a/site.cfg.example
+++ b/site.cfg.example
@@ -242,14 +242,6 @@
# library_dirs = C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2018\windows\mkl\lib\intel64
# libraries = mkl_rt
-# Accelerate
-# ----------
-# Accelerate/vecLib is an OSX framework providing a BLAS and LAPACK implementation.
-#
-# [accelerate]
-# libraries = Accelerate, vecLib
-# #libraries = None
-
# UMFPACK
# -------
# The UMFPACK library is used in scikits.umfpack to factor large sparse matrices.
diff --git a/test_requirements.txt b/test_requirements.txt
index 026bbe414..a555b8295 100644
--- a/test_requirements.txt
+++ b/test_requirements.txt
@@ -1,9 +1,15 @@
cython==0.29.19
hypothesis==5.16.0
-pytest==5.4.2
+pytest==5.4.3
pytz==2020.1
pytest-cov==2.9.0
pickle5; python_version == '3.7'
pickle5; python_version == '3.6' and platform_python_implementation != 'PyPy'
# for numpy.random.test.test_extending
cffi
+# For testing types. Notes on the restrictions:
+# - Mypy relies on C API features not present in PyPy
+# - Mypy doesn't currently work on Python 3.9
+# - Python 3.6 doesn't work because it doesn't understand py.typed
+mypy==0.770; platform_python_implementation != "PyPy" and python_version > "3.6" and python_version < "3.9"
+typing_extensions