From 0a6a8df577a72ce9b54fc2450ea6644b0ad770b7 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Fri, 27 Feb 2026 00:35:57 -0800 Subject: [PATCH 1/4] add pre-commit to the project --- .flake8 | 38 + .github/workflows/build-with-clang.yml | 2 +- .github/workflows/build_pip.yaml | 2 +- .github/workflows/conda-package.yml | 4 +- .pre-commit-config.yaml | 104 ++ CHANGELOG.md | 4 +- README.md | 2 +- _vendored/README.md | 2 +- conda-recipe-cf/build.sh | 11 +- conda-recipe-cf/run_tests.bat | 2 +- conda-recipe-cf/run_tests.sh | 1 + conda-recipe/build.sh | 11 +- conda-recipe/conda_build_config.yaml | 2 +- conda-recipe/run_tests.bat | 2 +- conda-recipe/run_tests.sh | 1 + mkl_umath/__init__.py | 14 +- mkl_umath/_version.py | 2 +- mkl_umath/generate_umath.py | 1383 +++++++++++++----------- mkl_umath/generate_umath_doc.py | 26 +- mkl_umath/src/_patch.pyx | 68 +- mkl_umath/src/blocking_utils.h | 58 +- mkl_umath/src/fast_loop_macros.h | 341 +++--- mkl_umath/src/mkl_umath_loops.c.src | 62 +- mkl_umath/src/mkl_umath_loops.h.src | 12 +- mkl_umath/src/ufuncsmodule.c | 68 +- mkl_umath/src/ufuncsmodule.h | 20 +- mkl_umath/tests/test_basic.py | 67 +- mkl_umath/ufunc_docstrings_numpy1.py | 661 +++++++---- mkl_umath/ufunc_docstrings_numpy2.py | 897 ++++++++++----- pyproject.toml | 86 +- setup.py | 43 +- 31 files changed, 2513 insertions(+), 1483 deletions(-) create mode 100644 .flake8 create mode 100644 .pre-commit-config.yaml diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..36cf71b --- /dev/null +++ b/.flake8 @@ -0,0 +1,38 @@ +[flake8] +extend-ignore = + # whitespace before ':' (currently conflicts with black formatting): + E203, + # ‘from module import *’ used; unable to detect undefined names: + F403, + # missing docstring in public module: + D100, + # missing docstring in public class: + D101, + # missing docstring in public method: + D102, + # missing docstring in public function: + D103, + # missing docstring in __init__: + D107, + # 1 blank line required between summary line and description: + D205, + # first line should end with a period: + D400, + # first line should be in imperative mood: + D401, + +per-file-ignores = + mkl_umath/__init__.py: F401 + mkl_umath/ufunc_docstrings_numpy1.py: E501 + mkl_umath/ufunc_docstrings_numpy2.py: E501 + +exclude = _vendored/conv_template.py + +filename = *.py, *.pyx, *.pxi, *.pxd +max_line_length = 80 +max-doc-length = 80 +show-source = True + +# Print detailed statistic if any issue detected +count = True +statistics = True diff --git a/.github/workflows/build-with-clang.yml b/.github/workflows/build-with-clang.yml index 93f0fed..6287681 100644 --- a/.github/workflows/build-with-clang.yml +++ b/.github/workflows/build-with-clang.yml @@ -74,7 +74,7 @@ jobs: run: | source ${{ env.ONEAPI_ROOT }}/setvars.sh pip install pytest - # mkl_umath cannot be installed in editable mode, we need + # mkl_umath cannot be installed in editable mode, we need # to change directory before importing it and running tests cd .. python -m pytest -sv --pyargs mkl_umath/mkl_umath/tests diff --git a/.github/workflows/build_pip.yaml b/.github/workflows/build_pip.yaml index bce5a59..511a54c 100644 --- a/.github/workflows/build_pip.yaml +++ b/.github/workflows/build_pip.yaml @@ -55,7 +55,7 @@ jobs: CC=icx pip install . --no-build-isolation --no-deps --verbose pip install --no-cache-dir pytest pip list - # mkl_umath cannot be installed in editable mode, we need + # mkl_umath cannot be installed in editable mode, we need # to change directory before importing it and running tests cd .. python -m pytest -v mkl_umath/mkl_umath/tests diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 472116c..b86d5c2 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -319,8 +319,8 @@ jobs: shell: cmd /C CALL {0} run: | conda activate - echo "Value of CONDA enviroment variable was: " %CONDA% - echo "Value of CONDA_PREFIX enviroment variable was: " %CONDA_PREFIX% + echo "Value of CONDA environment variable was: " %CONDA% + echo "Value of CONDA_PREFIX environment variable was: " %CONDA_PREFIX% conda info && conda list -n mkl_umath_test - name: Smoke test diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..646ef8c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,104 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-ast + - id: check-builtin-literals + - id: check-case-conflict + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: check-toml + - id: debug-statements + - id: destroyed-symlinks + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: mixed-line-ending + - id: trailing-whitespace + +- repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: + - id: python-check-blanket-noqa + - id: python-check-blanket-type-ignore + - id: python-check-mock-methods + - id: python-no-eval + - id: python-no-log-warn + - id: python-use-type-annotations + - id: rst-backticks + - id: rst-directive-colons + - id: rst-inline-touching-normal + - id: text-unicode-replacement-char + +- repo: https://github.com/codespell-project/codespell + rev: v2.4.1 + hooks: + - id: codespell + args: ["-L", "nin,inout"] + additional_dependencies: + - tomli + +- repo: https://github.com/psf/black + rev: 26.1.0 + hooks: + - id: black + exclude: "_vendored/conv_template.py" + +- repo: https://github.com/pocc/pre-commit-hooks + rev: v1.3.5 + hooks: + - id: clang-format + args: ["-i"] + +- repo: https://github.com/MarcoGorelli/cython-lint + rev: v0.19.0 + hooks: + - id: cython-lint + - id: double-quote-cython-strings + +- repo: https://github.com/pycqa/flake8 + rev: 7.3.0 + hooks: + - id: flake8 + args: ["--config=.flake8"] + additional_dependencies: + - flake8-docstrings==1.7.0 + - flake8-bugbear==25.11.29 + +- repo: https://github.com/pycqa/isort + rev: 8.0.0 + hooks: + - id: isort + name: isort (python) + - id: isort + name: isort (cython) + types: [cython] + - id: isort + name: isort (pyi) + types: [pyi] + +- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.16.0 + hooks: + - id: pretty-format-toml + args: [--autofix] + +- repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] + require_serial: true + args: + [ + "-rn", # Only display messages + "-sn", # Don't display the score + "--errors-only", + "--disable=import-error", + ] + +- repo: https://github.com/jumanjihouse/pre-commit-hooks + rev: 3.0.0 + hooks: + - id: shellcheck diff --git a/CHANGELOG.md b/CHANGELOG.md index ee581b9..0267756 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Enabled support of Python 3.13 [gh-101](https://github.com/IntelPython/mkl_umath/pull/101) * Added mkl implementation for complex data-types of `add`, `subtract`, `multiply` and `divide` functions [gh-102](https://github.com/IntelPython/mkl_umath/pull/102) -### Changed +### Changed * Dropped support for `maximum` and `minimum` [gh-104](https://github.com/IntelPython/mkl_umath/pull/104) * Disabled `-fast-math` by default [gh-105](https://github.com/IntelPython/mkl_umath/pull/105) * Used a common umath loop for `log2` function to match NumPy [gh-109](https://github.com/IntelPython/mkl_umath/pull/109) @@ -37,7 +37,7 @@ This release updates `mkl_umath` to be aligned with both numpy-1.26.x and numpy- * The definition of `sign` function for complex floating point data types is updated to match numpy-2.x.x [gh-65](https://github.com/IntelPython/mkl_umath/pull/65) * `ldexp` function is updated to allow `int64` explicitly similar to numpy-2.x.x behavior [gh-73](https://github.com/IntelPython/mkl_umath/pull/73) -### Changed +### Changed * Migrated from `setup.py` to `pyproject toml` [gh-63](https://github.com/IntelPython/mkl_umath/pull/63) * Changed to dynamic linking and added interface and threading layers [gh-72](https://github.com/IntelPython/mkl_umath/pull/72) diff --git a/README.md b/README.md index 494c712..91d5f31 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ powered version of loops used in the patched version of [NumPy](https://numpy.or Patches were factored out per community feedback ([NEP-36](https://numpy.org/neps/nep-0036-fair-play.html)). -`mkl_umath` started as a part of Intel® Distribution for Python* optimizations to NumPy, and is now being released +`mkl_umath` started as a part of Intel® Distribution for Python* optimizations to NumPy, and is now being released as a stand-alone package. It can be installed into conda environment using: ``` diff --git a/_vendored/README.md b/_vendored/README.md index 0ebafcb..b3f3a91 100644 --- a/_vendored/README.md +++ b/_vendored/README.md @@ -2,4 +2,4 @@ File `conv_template.py` is copied from NumPy's numpy/distutils folder, since `numpy.distutils` is absent from the installation layout starting with -Python 3.12 \ No newline at end of file +Python 3.12 diff --git a/conda-recipe-cf/build.sh b/conda-recipe-cf/build.sh index d83d1a7..155ca2c 100644 --- a/conda-recipe-cf/build.sh +++ b/conda-recipe-cf/build.sh @@ -1,9 +1,12 @@ +#!/bin/bash + # This is necessary to help DPC++ find Intel libraries such as SVML, IRNG, etc in build prefix export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${BUILD_PREFIX}/lib" # Intel LLVM must cooperate with compiler and sysroot from conda echo "--gcc-toolchain=${BUILD_PREFIX} --sysroot=${BUILD_PREFIX}/${HOST}/sysroot -target ${HOST}" > icx_for_conda.cfg -export ICXCFG="$(pwd)/icx_for_conda.cfg" +ICXCFG="$(pwd)/icx_for_conda.cfg" +export ICXCFG read -r GLIBC_MAJOR GLIBC_MINOR <<< "$(conda list '^sysroot_linux-64$' \ | tail -n 1 | awk '{print $2}' | grep -oP '\d+' | head -n 2 | tr '\n' ' ')" @@ -14,9 +17,9 @@ SKBUILD_ARGS="-- -DCMAKE_C_COMPILER:PATH=icx -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" if [ -n "${WHEELS_OUTPUT_FOLDER}" ]; then # Install packages and assemble wheel package from built bits WHEELS_BUILD_ARGS="-p manylinux_${GLIBC_MAJOR}_${GLIBC_MINOR}_x86_64" - ${PYTHON} setup.py install bdist_wheel ${WHEELS_BUILD_ARGS} ${SKBUILD_ARGS} - cp dist/mkl_umath*.whl ${WHEELS_OUTPUT_FOLDER} + ${PYTHON} setup.py install bdist_wheel "${WHEELS_BUILD_ARGS}" "${SKBUILD_ARGS}" + cp dist/mkl_umath*.whl "${WHEELS_OUTPUT_FOLDER}" else # Perform regular install - ${PYTHON} setup.py install ${SKBUILD_ARGS} + ${PYTHON} setup.py install "${SKBUILD_ARGS}" fi diff --git a/conda-recipe-cf/run_tests.bat b/conda-recipe-cf/run_tests.bat index 590db89..42b23a9 100644 --- a/conda-recipe-cf/run_tests.bat +++ b/conda-recipe-cf/run_tests.bat @@ -1 +1 @@ -%PYTHON% tests\test_basic.py \ No newline at end of file +%PYTHON% tests\test_basic.py diff --git a/conda-recipe-cf/run_tests.sh b/conda-recipe-cf/run_tests.sh index 7bfca5d..219a559 100644 --- a/conda-recipe-cf/run_tests.sh +++ b/conda-recipe-cf/run_tests.sh @@ -1 +1,2 @@ +#!/bin/bash $PYTHON tests/test_basic.py diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh index d83d1a7..155ca2c 100644 --- a/conda-recipe/build.sh +++ b/conda-recipe/build.sh @@ -1,9 +1,12 @@ +#!/bin/bash + # This is necessary to help DPC++ find Intel libraries such as SVML, IRNG, etc in build prefix export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${BUILD_PREFIX}/lib" # Intel LLVM must cooperate with compiler and sysroot from conda echo "--gcc-toolchain=${BUILD_PREFIX} --sysroot=${BUILD_PREFIX}/${HOST}/sysroot -target ${HOST}" > icx_for_conda.cfg -export ICXCFG="$(pwd)/icx_for_conda.cfg" +ICXCFG="$(pwd)/icx_for_conda.cfg" +export ICXCFG read -r GLIBC_MAJOR GLIBC_MINOR <<< "$(conda list '^sysroot_linux-64$' \ | tail -n 1 | awk '{print $2}' | grep -oP '\d+' | head -n 2 | tr '\n' ' ')" @@ -14,9 +17,9 @@ SKBUILD_ARGS="-- -DCMAKE_C_COMPILER:PATH=icx -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" if [ -n "${WHEELS_OUTPUT_FOLDER}" ]; then # Install packages and assemble wheel package from built bits WHEELS_BUILD_ARGS="-p manylinux_${GLIBC_MAJOR}_${GLIBC_MINOR}_x86_64" - ${PYTHON} setup.py install bdist_wheel ${WHEELS_BUILD_ARGS} ${SKBUILD_ARGS} - cp dist/mkl_umath*.whl ${WHEELS_OUTPUT_FOLDER} + ${PYTHON} setup.py install bdist_wheel "${WHEELS_BUILD_ARGS}" "${SKBUILD_ARGS}" + cp dist/mkl_umath*.whl "${WHEELS_OUTPUT_FOLDER}" else # Perform regular install - ${PYTHON} setup.py install ${SKBUILD_ARGS} + ${PYTHON} setup.py install "${SKBUILD_ARGS}" fi diff --git a/conda-recipe/conda_build_config.yaml b/conda-recipe/conda_build_config.yaml index b63eaf6..6f302ab 100644 --- a/conda-recipe/conda_build_config.yaml +++ b/conda-recipe/conda_build_config.yaml @@ -19,6 +19,6 @@ c_compiler: # [win] CFLAGS: - -fno-fast-math # [linux] CXXFLAGS: - - -fno-fast-math # [linux] + - -fno-fast-math # [linux] CL: - /fp:precise # [win] diff --git a/conda-recipe/run_tests.bat b/conda-recipe/run_tests.bat index 590db89..42b23a9 100644 --- a/conda-recipe/run_tests.bat +++ b/conda-recipe/run_tests.bat @@ -1 +1 @@ -%PYTHON% tests\test_basic.py \ No newline at end of file +%PYTHON% tests\test_basic.py diff --git a/conda-recipe/run_tests.sh b/conda-recipe/run_tests.sh index 7bfca5d..219a559 100644 --- a/conda-recipe/run_tests.sh +++ b/conda-recipe/run_tests.sh @@ -1 +1,2 @@ +#!/bin/bash $PYTHON tests/test_basic.py diff --git a/mkl_umath/__init__.py b/mkl_umath/__init__.py index 8838e8f..0477d5a 100644 --- a/mkl_umath/__init__.py +++ b/mkl_umath/__init__.py @@ -23,16 +23,16 @@ # 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. -''' -Implementation of Numpy universal math functions using Intel(R) MKL and Intel(R) C compiler runtime. -''' +""" +Implementation of Numpy universal math functions using Intel(R) MKL and +Intel(R) C compiler runtime. +""" from . import _init_helper - -from ._version import __version__ - +from ._patch import is_patched, mkl_umath, restore, use_in_numpy from ._ufuncs import * +from ._version import __version__ -from ._patch import mkl_umath, use_in_numpy, restore, is_patched +# TODO: add __all__ with public API and remove star imports del _init_helper diff --git a/mkl_umath/_version.py b/mkl_umath/_version.py index 7d8d060..99ba996 100644 --- a/mkl_umath/_version.py +++ b/mkl_umath/_version.py @@ -1 +1 @@ -__version__ = '0.4.0dev1' +__version__ = "0.4.0dev1" diff --git a/mkl_umath/generate_umath.py b/mkl_umath/generate_umath.py index 9de1112..31be813 100644 --- a/mkl_umath/generate_umath.py +++ b/mkl_umath/generate_umath.py @@ -27,7 +27,8 @@ # https://github.com/numpy/numpy/blob/maintenance/2.2.x/numpy/_core/code_generators/generate_umath.py # Differences with the NumPy file: # 1) The `defdict` dictionary is completely different. -# 2) In the `make_arrays` function, `cfunc_fname = f"{tname}_*"` is changed to `cfunc_fname = f"mkl_umath_{tname}_*"` +# 2) In the `make_arrays` function, `cfunc_fname = f"{tname}_*"` is changed to +# `cfunc_fname = f"mkl_umath_{tname}_*"` # 3) In the `make_ufuncs` function, line 988: `{doc}` is changed to `"{doc}"` # 4) In the `make_code` function, the string used there is different. @@ -36,10 +37,13 @@ a dictionary of Ufunc classes. This is fed to make_code to generate __umath_generated.c """ + +import argparse import os import re +import string import textwrap -import argparse + import numpy as np # identity objects @@ -49,9 +53,10 @@ False_ = "(Py_INCREF(Py_False), Py_False)" None_ = object() AllOnes = "PyLong_FromLong(-1)" -MinusInfinity = 'PyFloat_FromDouble(-NPY_INFINITY)' +MinusInfinity = "PyFloat_FromDouble(-NPY_INFINITY)" ReorderableNone = "(Py_INCREF(Py_None), Py_None)" + class docstrings: @staticmethod def get(place): @@ -60,19 +65,22 @@ def get(place): to ufunc place. C #definitions are generated by generate_umath_doc.py in a separate C header. """ - return 'DOC_' + place.upper().replace('.', '_') + return "DOC_" + place.upper().replace(".", "_") + # Sentinel value to specify using the full type description in the # function name class FullTypeDescr: pass + class FuncNameSuffix: - """Stores the suffix to append when generating functions names. - """ + """Stores the suffix to append when generating functions names.""" + def __init__(self, suffix): self.suffix = suffix + class TypeDescription: """Type signature for a ufunc. @@ -91,7 +99,8 @@ class TypeDescription: If astype['x'] is 'y', uses PyUFunc_x_x_As_y_y/PyUFunc_xx_x_As_yy_y instead of PyUFunc_x_x/PyUFunc_xx_x. cfunc_alias : str or none, optional - Appended to inner loop C function name, e.g., FLOAT_{cfunc_alias}. See make_arrays. + Appended to inner loop C function name, e.g., FLOAT_{cfunc_alias}. + See make_arrays. NOTE: it doesn't support 'astype' dispatch : str or None, optional Dispatch-able source name without its extension '.dispatch.c' that @@ -99,18 +108,27 @@ class TypeDescription: specified targets of the dispatch-able source. NOTE: it doesn't support 'astype' """ - def __init__(self, type, f=None, in_=None, out=None, astype=None, cfunc_alias=None, - dispatch=None): + + def __init__( + self, + type, + f=None, + in_=None, + out=None, + astype=None, + cfunc_alias=None, + dispatch=None, + ): self.type = type self.func_data = f if astype is None: astype = {} self.astype_dict = astype if in_ is not None: - in_ = in_.replace('P', type) + in_ = in_.replace("P", type) self.in_ = in_ if out is not None: - out = out.replace('P', type) + out = out.replace("P", type) self.out = out self.cfunc_alias = cfunc_alias self.dispatch = dispatch @@ -132,7 +150,7 @@ def _check_order(types1, types2): can be cast safely. """ # Insert kK (int64) after all other ints (assumes long long isn't larger) - dtype_order = bints + 'kK' + times + flts + cmplxP + "O" + dtype_order = bints + "kK" + times + flts + cmplxP + "O" for t1, t2 in zip(types1, types2): # We have no opinion on object or time ordering for now: if t1 in "OP" or t2 in "OP": @@ -153,7 +171,8 @@ def _check_order(types1, types2): return raise TypeError( - f"Input dtypes are unsorted or duplicate: {types1} and {types2}") + f"Input dtypes are unsorted or duplicate: {types1} and {types2}" + ) def check_td_order(tds): @@ -161,34 +180,41 @@ def check_td_order(tds): # often that SIMD additions added loops that do not even make some sense. # TODO: This should likely be a test and it would be nice if it rejected # duplicate entries as well (but we have many as of writing this). - signatures = [t.in_+t.out for t in tds] + signatures = [t.in_ + t.out for t in tds] for prev_i, sign in enumerate(signatures[1:]): - if sign in signatures[:prev_i+1]: + if sign in signatures[: prev_i + 1]: continue # allow duplicates... _check_order(signatures[prev_i], sign) _floatformat_map = dict( - e='npy_%sf', - f='npy_%sf', - d='npy_%s', - g='npy_%sl', - F='nc_%sf', - D='nc_%s', - G='nc_%sl' + e="npy_%sf", + f="npy_%sf", + d="npy_%s", + g="npy_%sl", + F="nc_%sf", + D="nc_%s", + G="nc_%sl", ) + def build_func_data(types, f): - func_data = [_floatformat_map.get(t, '%s') % (f,) for t in types] + func_data = [_floatformat_map.get(t, "%s") % (f,) for t in types] return func_data -def TD(types, f=None, astype=None, in_=None, out=None, cfunc_alias=None, - dispatch=None): - """ - Generate a TypeDescription instance for each item in types - """ + +def TD( + types, + f=None, + astype=None, + in_=None, + out=None, + cfunc_alias=None, + dispatch=None, +): + """Generate a TypeDescription instance for each item in types""" if f is not None: if isinstance(f, str): func_data = build_func_data(types, f) @@ -214,15 +240,23 @@ def TD(types, f=None, astype=None, in_=None, out=None, cfunc_alias=None, for t, fd, i, o in zip(types, func_data, in_, out): # [(dispatch file name without extension '.dispatch.c*', list of types)] if dispatch: - dispt = ([k for k, v in dispatch if t in v]+[None])[0] + dispt = ([k for k, v in dispatch if t in v] + [None])[0] else: dispt = None - tds.append(TypeDescription( - t, f=fd, in_=i, out=o, astype=astype, cfunc_alias=cfunc_alias, - dispatch=dispt - )) + tds.append( + TypeDescription( + t, + f=fd, + in_=i, + out=o, + astype=astype, + cfunc_alias=cfunc_alias, + dispatch=dispt, + ) + ) return tds + class Ufunc: """Description of a ufunc. @@ -237,8 +271,18 @@ class Ufunc: signature: a generalized ufunc signature (like for matmul) indexed: add indexed loops (ufunc.at) for these type characters """ - def __init__(self, nin, nout, identity, docstring, typereso, - *type_descriptions, signature=None, indexed=''): + + def __init__( + self, + nin, + nout, + identity, + docstring, + typereso, + *type_descriptions, + signature=None, + indexed="", + ): self.nin = nin self.nout = nout if identity is None: @@ -257,14 +301,14 @@ def __init__(self, nin, nout, identity, docstring, typereso, check_td_order(self.type_descriptions) -# String-handling utilities to avoid locale-dependence. +UPPER_TABLE = bytes.maketrans( + bytes(string.ascii_lowercase, "ascii"), + bytes(string.ascii_uppercase, "ascii"), +) -import string -UPPER_TABLE = bytes.maketrans(bytes(string.ascii_lowercase, "ascii"), - bytes(string.ascii_uppercase, "ascii")) def english_upper(s): - """ Apply English case rules to convert ASCII strings to all upper case. + """Apply English case rules to convert ASCII strings to all upper case. This is an internal utility function to replace calls to str.upper() such that we can avoid changing behavior with changing locales. In particular, @@ -293,9 +337,9 @@ def english_upper(s): return uppered -#each entry in defdict is a Ufunc object. +# each entry in defdict is a Ufunc object. -#name: [string of chars for which it is defined, +# name: [string of chars for which it is defined, # string of characters using func interface, # tuple of strings giving funcs for data, # (in, out), or (instr, outstr) giving the signature as character codes, @@ -305,76 +349,76 @@ def english_upper(s): # ] chartoname = { - '?': 'bool', - 'b': 'byte', - 'B': 'ubyte', - 'h': 'short', - 'H': 'ushort', - 'i': 'int', - 'I': 'uint', - 'l': 'long', - 'L': 'ulong', + "?": "bool", + "b": "byte", + "B": "ubyte", + "h": "short", + "H": "ushort", + "i": "int", + "I": "uint", + "l": "long", + "L": "ulong", # We sometimes need int64, but we have no obvious char for it, use k and # define it as `int64` below. - 'k': 'int64', - 'K': 'uint64', - 'q': 'longlong', - 'Q': 'ulonglong', - 'e': 'half', - 'f': 'float', - 'd': 'double', - 'g': 'longdouble', - 'F': 'cfloat', - 'D': 'cdouble', - 'G': 'clongdouble', - 'M': 'datetime', - 'm': 'timedelta', - 'O': 'OBJECT', + "k": "int64", + "K": "uint64", + "q": "longlong", + "Q": "ulonglong", + "e": "half", + "f": "float", + "d": "double", + "g": "longdouble", + "F": "cfloat", + "D": "cdouble", + "G": "clongdouble", + "M": "datetime", + "m": "timedelta", + "O": "OBJECT", # '.' is like 'O', but calls a method of the object instead # of a function - 'P': 'OBJECT', + "P": "OBJECT", } -no_obj_bool = 'bBhHiIlLqQefdgFDGmM' -noobj = '?' + no_obj_bool -all = '?bBhHiIlLqQefdgFDGOmM' - -O = 'O' -P = 'P' -ints = 'bBhHiIlLqQ' -sints = 'bhilq' -uints = 'BHILQ' -times = 'Mm' -timedeltaonly = 'm' +no_obj_bool = "bBhHiIlLqQefdgFDGmM" +noobj = "?" + no_obj_bool +all = "?bBhHiIlLqQefdgFDGOmM" + +O = "O" # noqa: E741 +P = "P" +ints = "bBhHiIlLqQ" +sints = "bhilq" +uints = "BHILQ" +times = "Mm" +timedeltaonly = "m" intsO = ints + O -bints = '?' + ints +bints = "?" + ints bintsO = bints + O -flts = 'efdg' +flts = "efdg" fltsO = flts + O fltsP = flts + P -cmplx = 'FDG' -cmplxvec = 'FD' +cmplx = "FDG" +cmplxvec = "FD" cmplxO = cmplx + O cmplxP = cmplx + P inexact = flts + cmplx -inexactvec = 'fd' -noint = inexact+O -nointP = inexact+P -allP = bints+times+flts+cmplxP +inexactvec = "fd" +noint = inexact + O +nointP = inexact + P +allP = bints + times + flts + cmplxP nobool_or_obj = noobj[1:] -nobool_or_datetime = noobj[1:-1] + O # includes m - timedelta64 -intflt = ints+flts -intfltcmplx = ints+flts+cmplx -nocmplx = bints+times+flts -nocmplxO = nocmplx+O -nocmplxP = nocmplx+P +nobool_or_datetime = noobj[1:-1] + O # includes m - timedelta64 +intflt = ints + flts +intfltcmplx = ints + flts + cmplx +nocmplx = bints + times + flts +nocmplxO = nocmplx + O +nocmplxP = nocmplx + P notimes_or_obj = bints + inexact nodatetime_or_obj = bints + inexact no_bool_times_obj = ints + inexact # Find which code corresponds to int64. -int64 = 'k' -uint64 = 'K' +int64 = "k" +uint64 = "K" # This dictionary describes all the ufunc implementations, generating # all the function names and their corresponding ufunc signatures. TD is @@ -383,495 +427,614 @@ def english_upper(s): if np.lib.NumpyVersion(np.__version__) < "2.0.0": ldexp_signature = [ - TypeDescription('f', None, 'fi', 'f'), - TypeDescription('f', FuncNameSuffix('long'), 'fl', 'f'), - TypeDescription('d', None, 'di', 'd'), - TypeDescription('d', FuncNameSuffix('long'), 'dl', 'd'), + TypeDescription("f", None, "fi", "f"), + TypeDescription("f", FuncNameSuffix("long"), "fl", "f"), + TypeDescription("d", None, "di", "d"), + TypeDescription("d", FuncNameSuffix("long"), "dl", "d"), ] else: ldexp_signature = [ - TypeDescription('f', None, 'fi', 'f'), - TypeDescription('f', FuncNameSuffix('int64'), 'f'+int64, 'f'), - TypeDescription('d', None, 'di', 'd'), - TypeDescription('d', FuncNameSuffix('int64'), 'd'+int64, 'd'), + TypeDescription("f", None, "fi", "f"), + TypeDescription("f", FuncNameSuffix("int64"), "f" + int64, "f"), + TypeDescription("d", None, "di", "d"), + TypeDescription("d", FuncNameSuffix("int64"), "d" + int64, "d"), ] defdict = { -'add': - Ufunc(2, 1, Zero, - docstrings.get('numpy._core.umath.add'), - None, - TD(inexactvec + cmplxvec), - ), -'subtract': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.subtract'), - None, - TD(inexactvec + cmplxvec), - ), -'multiply': - Ufunc(2, 1, One, - docstrings.get('numpy._core.umath.multiply'), - None, - TD(inexactvec + cmplxvec), - ), -# 'true_divide': aliased to divide -# 'floor_divide': -'divide': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.divide'), - None, - TD(inexactvec + cmplxvec), - ), -'conjugate': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.conjugate'), - None, - TD(inexactvec + cmplxvec), - ), -# 'fmod': -'square': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.square'), - None, - TD(inexactvec + cmplxvec), - ), -'reciprocal': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.reciprocal'), - None, - TD(inexactvec + cmplxvec), - ), -# '_ones_like': -# 'power': -# 'float_power': -'absolute': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.absolute'), - None, - TD(inexactvec), - TD('F', out='f'), - TD('D', out='d'), - ), -# '_arg': -'negative': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.negative'), - None, - TD(inexactvec), - ), -'positive': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.positive'), - None, - TD(inexactvec), - ), -'sign': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.sign'), - None, - TD(inexactvec + cmplxvec), - ), -'greater': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.greater'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'greater_equal': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.greater_equal'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'less': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.less'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'less_equal': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.less_equal'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'equal': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.equal'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'not_equal': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.not_equal'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'logical_and': - Ufunc(2, 1, True_, - docstrings.get('numpy._core.umath.logical_and'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'logical_not': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.logical_not'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'logical_or': - Ufunc(2, 1, False_, - docstrings.get('numpy._core.umath.logical_or'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'logical_xor': - Ufunc(2, 1, False_, - docstrings.get('numpy._core.umath.logical_xor'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -# 'maximum': no dedicated Intel(R) MKL function -# 'minimum': no dedicated Intel(R) MKL function -# 'clip': -'fmax': - Ufunc(2, 1, ReorderableNone, - docstrings.get('numpy._core.umath.fmax'), - None, - TD(inexactvec + cmplxvec), - ), -'fmin': - Ufunc(2, 1, ReorderableNone, - docstrings.get('numpy._core.umath.fmin'), - None, - TD(inexactvec + cmplxvec), - ), -# 'logaddexp': -# 'logaddexp2': -# 'bitwise_and': -# 'bitwise_or': -# 'bitwise_xor': -# 'invert': -# 'left_shift': -# 'right_shift': -# 'heaviside': -# 'degrees': -# 'rad2deg': -# 'radians': -# 'deg2rad': -'arccos': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.arccos'), - None, - TD(inexactvec), - ), -'arccosh': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.arccosh'), - None, - TD(inexactvec), - ), -'arcsin': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.arcsin'), - None, - TD(inexactvec), - ), -'arcsinh': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.arcsinh'), - None, - TD(inexactvec), - ), -'arctan': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.arctan'), - None, - TD(inexactvec), - ), -'arctanh': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.arctanh'), - None, - TD(inexactvec), - ), -'cos': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.cos'), - None, - TD(inexactvec), - ), -'sin': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.sin'), - None, - TD(inexactvec), - ), -'tan': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.tan'), - None, - TD(inexactvec), - ), -'cosh': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.cosh'), - None, - TD(inexactvec), - ), -'sinh': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.sinh'), - None, - TD(inexactvec), - ), -'tanh': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.tanh'), - None, - TD(inexactvec), - ), -'exp': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.exp'), - None, - TD(inexactvec), - ), -'exp2': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.exp2'), - None, - TD(inexactvec), - ), -'expm1': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.expm1'), - None, - TD(inexactvec), - ), -'log': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.log'), - None, - TD(inexactvec), - ), -'log2': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.log2'), - None, - TD(inexactvec), - ), -'log10': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.log10'), - None, - TD(inexactvec), - ), -'log1p': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.log1p'), - None, - TD(inexactvec), - ), -'sqrt': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.sqrt'), - None, - TD(inexactvec), - ), -'cbrt': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.cbrt'), - None, - TD(inexactvec), - ), -'ceil': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.ceil'), - None, - TD(inexactvec), - ), -'trunc': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.trunc'), - None, - TD(inexactvec), - ), -'fabs': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.fabs'), - None, - TD(inexactvec), - ), -'floor': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.floor'), - None, - TD(inexactvec), - ), -'rint': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.rint'), - None, - TD(inexactvec), - ), -# 'arctan2': -# 'remainder': Intel(R) MKL function v?Remainder follows C's modulo operator, -# but NumPy is expecting Python's one -# 'divmod': TODO: check if it can be added -# 'hypot': -'isnan': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.isnan'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -# 'isnat': -'isinf': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.isinf'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -'isfinite': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.isfinite'), - None, - TD(inexactvec + cmplxvec, out='?'), - ), -# 'signbit': -'copysign': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.copysign'), - None, - TD(inexactvec), - ), -'nextafter': - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.nextafter'), - None, - TD(inexactvec), - ), -'spacing': - Ufunc(1, 1, None, - docstrings.get('numpy._core.umath.spacing'), - None, - TD(inexactvec), - ), -'modf': - Ufunc(1, 2, None, - docstrings.get('numpy._core.umath.modf'), - None, - TD(inexactvec), - ), -'ldexp' : - Ufunc(2, 1, None, - docstrings.get('numpy._core.umath.ldexp'), - None, - ldexp_signature, - ), -'frexp' : - Ufunc(1, 2, None, - docstrings.get('numpy._core.umath.frexp'), - None, - [ - TypeDescription('f', None, 'f', 'fi'), - TypeDescription('d', None, 'd', 'di'), - ], - ), -# 'gcd': -# 'lcm': -# 'bitwise_count': -# 'matmul': -# 'vecdot': -# 'matvec': -# 'vecmat': -# 'str_len': -# 'isalpha': -# 'isdigit': -# 'isspace': -# 'isalnum': -# 'islower': -# 'isupper': -# 'istitle': -# 'isdecimal': -# 'isnumeric': -# 'find': -# 'rfind': -# 'count': -# 'index': -# 'rindex': -# '_replace': -# 'startswith': -# 'endswith': -# '_strip_chars': -# '_lstrip_chars': -# '_rstrip_chars': -# '_strip_whitespace': -# '_lstrip_whitespace': -# '_rstrip_whitespace':, -# '_expandtabs_length': -# '_expandtabs': -# '_center': -# '_ljust': -# '_rjust': -# '_zfill': -# '_partition_index': -# '_rpartition_index': -# '_partition': -# '_rpartition': -# '_slice': + "add": Ufunc( + 2, + 1, + Zero, + docstrings.get("numpy._core.umath.add"), + None, + TD(inexactvec + cmplxvec), + ), + "subtract": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.subtract"), + None, + TD(inexactvec + cmplxvec), + ), + "multiply": Ufunc( + 2, + 1, + One, + docstrings.get("numpy._core.umath.multiply"), + None, + TD(inexactvec + cmplxvec), + ), + # 'true_divide': aliased to divide + # 'floor_divide': + "divide": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.divide"), + None, + TD(inexactvec + cmplxvec), + ), + "conjugate": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.conjugate"), + None, + TD(inexactvec + cmplxvec), + ), + # 'fmod': + "square": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.square"), + None, + TD(inexactvec + cmplxvec), + ), + "reciprocal": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.reciprocal"), + None, + TD(inexactvec + cmplxvec), + ), + # '_ones_like': + # 'power': + # 'float_power': + "absolute": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.absolute"), + None, + TD(inexactvec), + TD("F", out="f"), + TD("D", out="d"), + ), + # '_arg': + "negative": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.negative"), + None, + TD(inexactvec), + ), + "positive": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.positive"), + None, + TD(inexactvec), + ), + "sign": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.sign"), + None, + TD(inexactvec + cmplxvec), + ), + "greater": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.greater"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "greater_equal": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.greater_equal"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "less": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.less"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "less_equal": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.less_equal"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "equal": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.equal"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "not_equal": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.not_equal"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "logical_and": Ufunc( + 2, + 1, + True_, + docstrings.get("numpy._core.umath.logical_and"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "logical_not": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.logical_not"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "logical_or": Ufunc( + 2, + 1, + False_, + docstrings.get("numpy._core.umath.logical_or"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "logical_xor": Ufunc( + 2, + 1, + False_, + docstrings.get("numpy._core.umath.logical_xor"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + # 'maximum': no dedicated Intel(R) MKL function + # 'minimum': no dedicated Intel(R) MKL function + # 'clip': + "fmax": Ufunc( + 2, + 1, + ReorderableNone, + docstrings.get("numpy._core.umath.fmax"), + None, + TD(inexactvec + cmplxvec), + ), + "fmin": Ufunc( + 2, + 1, + ReorderableNone, + docstrings.get("numpy._core.umath.fmin"), + None, + TD(inexactvec + cmplxvec), + ), + # 'logaddexp': + # 'logaddexp2': + # 'bitwise_and': + # 'bitwise_or': + # 'bitwise_xor': + # 'invert': + # 'left_shift': + # 'right_shift': + # 'heaviside': + # 'degrees': + # 'rad2deg': + # 'radians': + # 'deg2rad': + "arccos": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.arccos"), + None, + TD(inexactvec), + ), + "arccosh": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.arccosh"), + None, + TD(inexactvec), + ), + "arcsin": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.arcsin"), + None, + TD(inexactvec), + ), + "arcsinh": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.arcsinh"), + None, + TD(inexactvec), + ), + "arctan": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.arctan"), + None, + TD(inexactvec), + ), + "arctanh": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.arctanh"), + None, + TD(inexactvec), + ), + "cos": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.cos"), + None, + TD(inexactvec), + ), + "sin": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.sin"), + None, + TD(inexactvec), + ), + "tan": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.tan"), + None, + TD(inexactvec), + ), + "cosh": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.cosh"), + None, + TD(inexactvec), + ), + "sinh": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.sinh"), + None, + TD(inexactvec), + ), + "tanh": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.tanh"), + None, + TD(inexactvec), + ), + "exp": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.exp"), + None, + TD(inexactvec), + ), + "exp2": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.exp2"), + None, + TD(inexactvec), + ), + "expm1": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.expm1"), + None, + TD(inexactvec), + ), + "log": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.log"), + None, + TD(inexactvec), + ), + "log2": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.log2"), + None, + TD(inexactvec), + ), + "log10": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.log10"), + None, + TD(inexactvec), + ), + "log1p": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.log1p"), + None, + TD(inexactvec), + ), + "sqrt": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.sqrt"), + None, + TD(inexactvec), + ), + "cbrt": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.cbrt"), + None, + TD(inexactvec), + ), + "ceil": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.ceil"), + None, + TD(inexactvec), + ), + "trunc": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.trunc"), + None, + TD(inexactvec), + ), + "fabs": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.fabs"), + None, + TD(inexactvec), + ), + "floor": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.floor"), + None, + TD(inexactvec), + ), + "rint": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.rint"), + None, + TD(inexactvec), + ), + # 'arctan2': + # 'remainder': Intel(R) MKL function v?Remainder follows C's modulo + # operator, but NumPy is expecting Python's one + # 'divmod': TODO: check if it can be added + # 'hypot': + "isnan": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.isnan"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + # 'isnat': + "isinf": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.isinf"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + "isfinite": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.isfinite"), + None, + TD(inexactvec + cmplxvec, out="?"), + ), + # 'signbit': + "copysign": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.copysign"), + None, + TD(inexactvec), + ), + "nextafter": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.nextafter"), + None, + TD(inexactvec), + ), + "spacing": Ufunc( + 1, + 1, + None, + docstrings.get("numpy._core.umath.spacing"), + None, + TD(inexactvec), + ), + "modf": Ufunc( + 1, + 2, + None, + docstrings.get("numpy._core.umath.modf"), + None, + TD(inexactvec), + ), + "ldexp": Ufunc( + 2, + 1, + None, + docstrings.get("numpy._core.umath.ldexp"), + None, + ldexp_signature, + ), + "frexp": Ufunc( + 1, + 2, + None, + docstrings.get("numpy._core.umath.frexp"), + None, + [ + TypeDescription("f", None, "f", "fi"), + TypeDescription("d", None, "d", "di"), + ], + ), + # 'gcd': + # 'lcm': + # 'bitwise_count': + # 'matmul': + # 'vecdot': + # 'matvec': + # 'vecmat': + # 'str_len': + # 'isalpha': + # 'isdigit': + # 'isspace': + # 'isalnum': + # 'islower': + # 'isupper': + # 'istitle': + # 'isdecimal': + # 'isnumeric': + # 'find': + # 'rfind': + # 'count': + # 'index': + # 'rindex': + # '_replace': + # 'startswith': + # 'endswith': + # '_strip_chars': + # '_lstrip_chars': + # '_rstrip_chars': + # '_strip_whitespace': + # '_lstrip_whitespace': + # '_rstrip_whitespace':, + # '_expandtabs_length': + # '_expandtabs': + # '_center': + # '_ljust': + # '_rjust': + # '_zfill': + # '_partition_index': + # '_rpartition_index': + # '_partition': + # '_rpartition': + # '_slice': } + def indent(st, spaces): - indentation = ' '*spaces - indented = indentation + st.replace('\n', '\n'+indentation) + indentation = " " * spaces + indented = indentation + st.replace("\n", "\n" + indentation) # trim off any trailing spaces - indented = re.sub(r' +$', r'', indented) + indented = re.sub(r" +$", r"", indented) return indented + # maps [nin, nout][type] to a suffix arity_lookup = { (1, 1): { - 'e': 'e_e', - 'f': 'f_f', - 'd': 'd_d', - 'g': 'g_g', - 'F': 'F_F', - 'D': 'D_D', - 'G': 'G_G', - 'O': 'O_O', - 'P': 'O_O_method', + "e": "e_e", + "f": "f_f", + "d": "d_d", + "g": "g_g", + "F": "F_F", + "D": "D_D", + "G": "G_G", + "O": "O_O", + "P": "O_O_method", }, (2, 1): { - 'e': 'ee_e', - 'f': 'ff_f', - 'd': 'dd_d', - 'g': 'gg_g', - 'F': 'FF_F', - 'D': 'DD_D', - 'G': 'GG_G', - 'O': 'OO_O', - 'P': 'OO_O_method', + "e": "ee_e", + "f": "ff_f", + "d": "dd_d", + "g": "gg_g", + "F": "FF_F", + "D": "DD_D", + "G": "GG_G", + "O": "OO_O", + "P": "OO_O_method", }, (3, 1): { - 'O': 'OOO_O', - } + "O": "OOO_O", + }, } -#for each name +# for each name # 1) create functions, data, and signature # 2) fill in functions and data in InitOperators # 3) add function. + def make_arrays(funcdict): # functions array contains an entry for every type implemented NULL # should be placed where PyUfunc_ style function will be filled in # later code1list = [] code2list = [] - dispdict = {} + dispdict = {} names = sorted(funcdict.keys()) for name in names: uf = funcdict[name] @@ -885,47 +1048,55 @@ def make_arrays(funcdict): cfunc_fname = None if t.func_data is FullTypeDescr: tname = english_upper(chartoname[t.type]) - datalist.append('(void *)NULL') + datalist.append("(void *)NULL") if t.out == "?": - cfunc_fname = f"mkl_umath_{tname}_{t.in_}_bool_{cfunc_alias}" + cfunc_fname = ( + f"mkl_umath_{tname}_{t.in_}_bool_{cfunc_alias}" + ) else: - cfunc_fname = f"mkl_umath_{tname}_{t.in_}_{t.out}_{cfunc_alias}" + cfunc_fname = ( + f"mkl_umath_{tname}_{t.in_}_{t.out}_{cfunc_alias}" + ) elif isinstance(t.func_data, FuncNameSuffix): - datalist.append('(void *)NULL') + datalist.append("(void *)NULL") tname = english_upper(chartoname[t.type]) - cfunc_fname = f"mkl_umath_{tname}_{cfunc_alias}_{t.func_data.suffix}" + cfunc_fname = ( + f"mkl_umath_{tname}_{cfunc_alias}_{t.func_data.suffix}" + ) elif t.func_data is None: - datalist.append('(void *)NULL') + datalist.append("(void *)NULL") tname = english_upper(chartoname[t.type]) cfunc_fname = f"mkl_umath_{tname}_{cfunc_alias}" else: try: thedict = arity_lookup[uf.nin, uf.nout] - except KeyError as e: + except KeyError: raise ValueError( f"Could not handle {name}[{t.type}] " f"with nin={uf.nin}, nout={uf.nout}" ) from None - astype = '' + astype = "" if t.astype is not None: - astype = '_As_%s' % thedict[t.astype] - astr = ('%s_functions[%d] = PyUFunc_%s%s;' % - (name, k, thedict[t.type], astype)) + astype = "_As_%s" % thedict[t.astype] + astr = "%s_functions[%d] = PyUFunc_%s%s;" % ( + name, + k, + thedict[t.type], + astype, + ) code2list.append(astr) - if t.type == 'O': - astr = ('%s_data[%d] = (void *) %s;' % - (name, k, t.func_data)) + if t.type == "O": + astr = "%s_data[%d] = (void *) %s;" % (name, k, t.func_data) code2list.append(astr) - datalist.append('(void *)NULL') - elif t.type == 'P': + datalist.append("(void *)NULL") + elif t.type == "P": datalist.append('(void *)"%s"' % t.func_data) else: - astr = ('%s_data[%d] = (void *) %s;' % - (name, k, t.func_data)) + astr = "%s_data[%d] = (void *) %s;" % (name, k, t.func_data) code2list.append(astr) - datalist.append('(void *)NULL') - #datalist.append('(void *)%s' % t.func_data) + datalist.append("(void *)NULL") + # datalist.append('(void *)%s' % t.func_data) sub += 1 if cfunc_fname: @@ -935,22 +1106,25 @@ def make_arrays(funcdict): (name, k, cfunc_fname, t.in_ + t.out) ) else: - funclist.append('NULL') + funclist.append("NULL") for x in t.in_ + t.out: - siglist.append('NPY_%s' % (english_upper(chartoname[x]),)) + siglist.append("NPY_%s" % (english_upper(chartoname[x]),)) if funclist or siglist or datalist: - funcnames = ', '.join(funclist) - signames = ', '.join(siglist) - datanames = ', '.join(datalist) + funcnames = ", ".join(funclist) + signames = ", ".join(siglist) + datanames = ", ".join(datalist) code1list.append( "static PyUFuncGenericFunction %s_functions[] = {%s};" - % (name, funcnames)) - code1list.append("static void * %s_data[] = {%s};" - % (name, datanames)) - code1list.append("static const char %s_signatures[] = {%s};" - % (name, signames)) + % (name, funcnames) + ) + code1list.append( + "static void * %s_data[] = {%s};" % (name, datanames) + ) + code1list.append( + "static const char %s_signatures[] = {%s};" % (name, signames) + ) uf.empty = False else: uf.empty = True @@ -961,13 +1135,14 @@ def make_arrays(funcdict): #include "{dname}.dispatch.h" #endif """)) - for (ufunc_name, func_idx, cfunc_name, inout) in funcs: + for ufunc_name, func_idx, cfunc_name, inout in funcs: code2list.append(textwrap.dedent(f"""\ NPY_CPU_DISPATCH_TRACE("{ufunc_name}", "{''.join(inout)}"); - NPY_CPU_DISPATCH_CALL_XB({ufunc_name}_functions[{func_idx}] = {cfunc_name}); + NPY_CPU_DISPATCH_CALL_XB({ufunc_name}_functions[{func_idx}] = {cfunc_name}); # noqa: E501 """)) return "\n".join(code1list), "\n".join(code2list) + def make_ufuncs(funcdict): code3list = [] names = sorted(funcdict.keys()) @@ -1001,9 +1176,10 @@ def make_ufuncs(funcdict): data=f"{name}_data" if not uf.empty else "NULL", signatures=f"{name}_signatures" if not uf.empty else "NULL", nloops=len(uf.type_descriptions), - nin=uf.nin, nout=uf.nout, - has_identity='0' if uf.identity is None_ else '1', - identity='PyUFunc_IdentityValue', + nin=uf.nin, + nout=uf.nout, + has_identity="0" if uf.identity is None_ else "1", + identity="PyUFunc_IdentityValue", identity_expr=uf.identity, doc=uf.docstring, sig=sig, @@ -1012,13 +1188,14 @@ def make_ufuncs(funcdict): # Only PyUFunc_None means don't reorder - we pass this using the old # argument if uf.identity is None_: - args['identity'] = 'PyUFunc_None' - args['identity_expr'] = 'NULL' + args["identity"] = "PyUFunc_None" + args["identity_expr"] = "NULL" mlist.append(fmt.format(**args)) if uf.typereso is not None: mlist.append( - r"((PyUFuncObject *)f)->type_resolver = &%s;" % uf.typereso) + r"((PyUFuncObject *)f)->type_resolver = &%s;" % uf.typereso + ) for c in uf.indexed: # Handle indexed loops by getting the underlying ArrayMethodObject # from the list in f._loops and setting its field appropriately @@ -1046,17 +1223,20 @@ def make_ufuncs(funcdict): /* info is borrowed, no need to decref*/ }} """) - mlist.append(fmt.format( - typenum=f"NPY_{english_upper(chartoname[c])}", - count=uf.nin+uf.nout, - name=name, - funcname = f"{english_upper(chartoname[c])}_{name}_indexed", - )) + mlist.append( + fmt.format( + typenum=f"NPY_{english_upper(chartoname[c])}", + count=uf.nin + uf.nout, + name=name, + funcname=f"{english_upper(chartoname[c])}_{name}_indexed", + ) + ) mlist.append(r"""PyDict_SetItemString(dictionary, "%s", f);""" % name) mlist.append(r"""Py_DECREF(f);""") - code3list.append('\n'.join(mlist)) - return '\n'.join(code3list) + code3list.append("\n".join(mlist)) + return "\n".join(code3list) + def make_code(funcdict, filename): code1, code2 = make_arrays(funcdict) @@ -1092,10 +1272,7 @@ def make_code(funcdict, filename): def main(): parser = argparse.ArgumentParser() parser.add_argument( - "-o", - "--outfile", - type=str, - help="Path to the output directory" + "-o", "--outfile", type=str, help="Path to the output directory" ) args = parser.parse_args() @@ -1105,11 +1282,11 @@ def main(): if not args.outfile: # This is the distutils-based build - outfile = '__umath_generated.c' + outfile = "__umath_generated.c" else: outfile = os.path.join(os.getcwd(), args.outfile) - with open(outfile, 'w') as f: + with open(outfile, "w") as f: f.write(code) diff --git a/mkl_umath/generate_umath_doc.py b/mkl_umath/generate_umath_doc.py index 0057064..7ffff75 100644 --- a/mkl_umath/generate_umath_doc.py +++ b/mkl_umath/generate_umath_doc.py @@ -23,13 +23,14 @@ # 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. -# Adapted from +# Adapted from # https://github.com/numpy/numpy/blob/maintenance/2.2.x/numpy/_core/code_generators/generate_umath_doc.py -import sys +import argparse import os +import sys import textwrap -import argparse + import numpy as np sys.path.insert(0, os.path.dirname(__file__)) @@ -39,19 +40,21 @@ import ufunc_docstrings_numpy2 as docstrings sys.path.pop(0) + def normalize_doc(docstring): docstring = textwrap.dedent(docstring).strip() - docstring = docstring.encode('unicode-escape').decode('ascii') - docstring = docstring.replace(r'"', r'\"') + docstring = docstring.encode("unicode-escape").decode("ascii") + docstring = docstring.replace(r'"', r"\"") docstring = docstring.replace(r"'", r"\'") # Split the docstring because some compilers (like MS) do not like big # string literal in C code. We split at endlines because textwrap.wrap # do not play well with \n - docstring = '\\n\"\"'.join(docstring.split(r"\n")) + docstring = '\\n""'.join(docstring.split(r"\n")) return docstring + def write_code(target): - with open(target, 'w') as fid: + with open(target, "w") as fid: fid.write( "#ifndef NUMPY_CORE_INCLUDE__UMATH_DOC_GENERATED_H_\n" "#define NUMPY_CORE_INCLUDE__UMATH_DOC_GENERATED_H_\n" @@ -59,17 +62,14 @@ def write_code(target): for place, string in docstrings.docdict.items(): cdef_name = f"DOC_{place.upper().replace('.', '_')}" cdef_str = normalize_doc(string) - fid.write(f"#define {cdef_name} \"{cdef_str}\"\n") + fid.write(f'#define {cdef_name} "{cdef_str}"\n') fid.write("#endif //NUMPY_CORE_INCLUDE__UMATH_DOC_GENERATED_H\n") def main(): parser = argparse.ArgumentParser() parser.add_argument( - "-o", - "--outfile", - type=str, - help="Path to the output directory" + "-o", "--outfile", type=str, help="Path to the output directory" ) args = parser.parse_args() @@ -77,5 +77,5 @@ def main(): write_code(outfile) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/mkl_umath/src/_patch.pyx b/mkl_umath/src/_patch.pyx index 21bdfc1..8d2d299 100644 --- a/mkl_umath/src/_patch.pyx +++ b/mkl_umath/src/_patch.pyx @@ -29,9 +29,10 @@ import mkl_umath._ufuncs as mu cimport numpy as cnp + import numpy as np -from libc.stdlib cimport malloc, free +from libc.stdlib cimport free, malloc cnp.import_umath() @@ -60,7 +61,9 @@ cdef class patch: mkl_umath = getattr(mu, umath) self.functions_count += mkl_umath.ntypes - self.functions = malloc(self.functions_count * sizeof(function_info)) + self.functions = malloc( + self.functions_count * sizeof(function_info) + ) func_number = 0 for umath in umaths: @@ -73,22 +76,38 @@ cdef class patch: while oi < c_orig_umath.ntypes: found = True for i in range(c_patch_umath.nargs): - if c_patch_umath.types[pi * nargs + i] != c_orig_umath.types[oi * nargs + i]: + if ( + c_patch_umath.types[pi * nargs + i] + != c_orig_umath.types[oi * nargs + i] + ): found = False break - if found == True: + if found is True: break oi = oi + 1 if oi < c_orig_umath.ntypes: - self.functions[func_number].original_function = c_orig_umath.functions[oi] - self.functions[func_number].patch_function = c_patch_umath.functions[pi] - self.functions[func_number].signature = malloc(nargs * sizeof(int)) + self.functions[func_number].original_function = ( + c_orig_umath.functions[oi] + ) + self.functions[func_number].patch_function = ( + c_patch_umath.functions[pi] + ) + self.functions[func_number].signature = ( + malloc(nargs * sizeof(int)) + ) for i in range(nargs): - self.functions[func_number].signature[i] = c_patch_umath.types[pi * nargs + i] - self.functions_dict[(umath, patch_umath.types[pi])] = func_number + self.functions[func_number].signature[i] = ( + c_patch_umath.types[pi * nargs + i] + ) + self.functions_dict[(umath, patch_umath.types[pi])] = ( + func_number + ) func_number = func_number + 1 else: - raise RuntimeError("Unable to find original function for: " + umath + " " + patch_umath.types[pi]) + raise RuntimeError( + f"Unable to find original function for: {umath} " + f"{patch_umath.types[pi]}" + ) def __dealloc__(self): for i in range(self.functions_count): @@ -96,7 +115,7 @@ cdef class patch: free(self.functions) def do_patch(self): - cdef int res + cdef int _res cdef cnp.PyUFuncGenericFunction temp cdef cnp.PyUFuncGenericFunction function cdef int* signature @@ -106,12 +125,15 @@ cdef class patch: index = self.functions_dict[func] function = self.functions[index].patch_function signature = self.functions[index].signature - res = cnp.PyUFunc_ReplaceLoopBySignature(np_umath, function, signature, &temp) + # TODO: check res, 0 means success, -1 means error + _res = cnp.PyUFunc_ReplaceLoopBySignature( + np_umath, function, signature, &temp + ) self._is_patched = True def do_unpatch(self): - cdef int res + cdef int _res cdef cnp.PyUFuncGenericFunction temp cdef cnp.PyUFuncGenericFunction function cdef int* signature @@ -121,7 +143,10 @@ cdef class patch: index = self.functions_dict[func] function = self.functions[index].original_function signature = self.functions[index].signature - res = cnp.PyUFunc_ReplaceLoopBySignature(np_umath, function, signature, &temp) + # TODO: check res, 0 means success, -1 means error + _res = cnp.PyUFunc_ReplaceLoopBySignature( + np_umath, function, signature, &temp + ) self._is_patched = False @@ -129,11 +154,12 @@ cdef class patch: return self._is_patched from threading import local as threading_local + _tls = threading_local() def _is_tls_initialized(): - return (getattr(_tls, 'initialized', None) is not None) and (_tls.initialized == True) + return getattr(_tls, "initialized", False) def _initialize_tls(): @@ -158,7 +184,7 @@ def use_in_numpy(): >>> mkl_umath.restore() # Disable mkl_umath in Numpy >>> mkl_umath.is_patched() # False - + """ if not _is_tls_initialized(): _initialize_tls() @@ -181,7 +207,7 @@ def restore(): >>> mkl_umath.restore() # Disable mkl_umath in Numpy >>> mkl_umath.is_patched() - # False + # False """ if not _is_tls_initialized(): @@ -205,18 +231,20 @@ def is_patched(): >>> mkl_umath.restore() # Disable mkl_umath in Numpy >>> mkl_umath.is_patched() - # False + # False """ if not _is_tls_initialized(): _initialize_tls() return _tls.patch.is_patched() + from contextlib import ContextDecorator + class mkl_umath(ContextDecorator): """ - Context manager and decorator to temporarily patch NumPy ufuncs + Context manager and decorator to temporarily patch NumPy ufuncs with MKL-based implementations. Examples @@ -230,7 +258,7 @@ class mkl_umath(ContextDecorator): # True >>> mkl_umath.is_patched() - # False + # False """ def __enter__(self): diff --git a/mkl_umath/src/blocking_utils.h b/mkl_umath/src/blocking_utils.h index 7e5e433..071baa8 100644 --- a/mkl_umath/src/blocking_utils.h +++ b/mkl_umath/src/blocking_utils.h @@ -15,19 +15,20 @@ * * 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. + * 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. */ #include "numpy/arrayobject.h" -/* Adapted from NumPy's source code. +/* Adapted from NumPy's source code. * https://github.com/numpy/numpy/blob/main/LICENSE.txt */ /* @@ -38,17 +39,17 @@ * blocking. See the 'npy_blocked_end' function documentation below for an * example of how this function is used. */ -static NPY_INLINE npy_intp -npy_aligned_block_offset(const void * addr, const npy_uintp esize, - const npy_uintp alignment, const npy_uintp nvals) -{ - npy_uintp offset, peel; +static NPY_INLINE npy_intp npy_aligned_block_offset(const void *addr, + const npy_uintp esize, + const npy_uintp alignment, + const npy_uintp nvals) { + npy_uintp offset, peel; - offset = (npy_uintp)addr & (alignment - 1); - peel = offset ? (alignment - offset) / esize : 0; - peel = (peel <= nvals) ? peel : nvals; - assert(peel <= NPY_MAX_INTP); - return (npy_intp)peel; + offset = (npy_uintp)addr & (alignment - 1); + peel = offset ? (alignment - offset) / esize : 0; + peel = (peel <= nvals) ? peel : nvals; + assert(peel <= NPY_MAX_INTP); + return (npy_intp)peel; } /* @@ -71,15 +72,14 @@ npy_aligned_block_offset(const void * addr, const npy_uintp esize, * for(; i < n; i++) * */ -static NPY_INLINE npy_intp -npy_blocked_end(const npy_uintp peel, const npy_uintp esize, - const npy_uintp vsz, const npy_uintp nvals) -{ - npy_uintp ndiff = nvals - peel; - npy_uintp res = (ndiff - ndiff % (vsz / esize)); +static NPY_INLINE npy_intp npy_blocked_end(const npy_uintp peel, + const npy_uintp esize, + const npy_uintp vsz, + const npy_uintp nvals) { + npy_uintp ndiff = nvals - peel; + npy_uintp res = (ndiff - ndiff % (vsz / esize)); - assert(nvals >= peel); - assert(res <= NPY_MAX_INTP); - return (npy_intp)(res); + assert(nvals >= peel); + assert(res <= NPY_MAX_INTP); + return (npy_intp)(res); } - diff --git a/mkl_umath/src/fast_loop_macros.h b/mkl_umath/src/fast_loop_macros.h index 3daf032..12f9b07 100644 --- a/mkl_umath/src/fast_loop_macros.h +++ b/mkl_umath/src/fast_loop_macros.h @@ -15,14 +15,15 @@ * * 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. + * 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. */ /** @@ -34,6 +35,8 @@ * npy_intp *dimensions * npy_intp *steps */ + +// clang-format off #ifndef _NPY_UMATH_FAST_LOOP_MACROS_H_ #define _NPY_UMATH_FAST_LOOP_MACROS_H_ @@ -48,10 +51,11 @@ #else #define NPY_PRAGMA_VECTOR _Pragma("GCC ivdep") #define NPY_PRAGMA_NOVECTOR -#define NPY_ASSUME_ALIGNED(p, b) +#define NPY_ASSUME_ALIGNED(p, b) #endif +// clang-format on -/* Adapted from NumPy's source code. +/* Adapted from NumPy's source code. * https://github.com/numpy/numpy/blob/main/LICENSE.txt */ /** @@ -61,94 +65,91 @@ */ /** () -> (op1) */ -#define OUTPUT_LOOP\ - char *op1 = args[1];\ - npy_intp os1 = steps[1];\ - npy_intp n = dimensions[0];\ - npy_intp i;\ - for(i = 0; i < n; i++, op1 += os1) +#define OUTPUT_LOOP \ + char *op1 = args[1]; \ + npy_intp os1 = steps[1]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + for (i = 0; i < n; i++, op1 += os1) /** (ip1) -> (op1) */ -#define UNARY_LOOP\ - char *ip1 = args[0], *op1 = args[1];\ - npy_intp is1 = steps[0], os1 = steps[1];\ - npy_intp n = dimensions[0];\ - npy_intp i;\ - for(i = 0; i < n; ++i, ip1 += is1, op1 += os1) +#define UNARY_LOOP \ + char *ip1 = args[0], *op1 = args[1]; \ + npy_intp is1 = steps[0], os1 = steps[1]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + for (i = 0; i < n; ++i, ip1 += is1, op1 += os1) -#define UNARY_LOOP_VECTORIZED(tin, tout)\ - tin *ip1 = (tin *) args[0];\ - tout *op1 = (tout *) args[1]; \ - npy_intp n = dimensions[0];\ - npy_intp i;\ - NPY_PRAGMA_VECTOR\ - for(i = 0; i < n; ++i, ++ip1, ++op1) +#define UNARY_LOOP_VECTORIZED(tin, tout) \ + tin *ip1 = (tin *)args[0]; \ + tout *op1 = (tout *)args[1]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + NPY_PRAGMA_VECTOR \ + for (i = 0; i < n; ++i, ++ip1, ++op1) -#define UNARY_LOOP_DISPATCH(tin, tout, cond, body)\ - if (cond) {\ - UNARY_LOOP_VECTORIZED(tin, tout) { body; }\ - } else {\ - UNARY_LOOP { body; }\ - } +#define UNARY_LOOP_DISPATCH(tin, tout, cond, body) \ + if (cond) { \ + UNARY_LOOP_VECTORIZED(tin, tout) { body; } \ + } else { \ + UNARY_LOOP { body; } \ + } /** (ip1) -> (op1, op2) */ -#define UNARY_LOOP_TWO_OUT\ - char *ip1 = args[0], *op1 = args[1], *op2 = args[2];\ - npy_intp is1 = steps[0], os1 = steps[1], os2 = steps[2];\ - npy_intp n = dimensions[0];\ - npy_intp i;\ - for(i = 0; i < n; ++i, ip1 += is1, op1 += os1, op2 += os2) +#define UNARY_LOOP_TWO_OUT \ + char *ip1 = args[0], *op1 = args[1], *op2 = args[2]; \ + npy_intp is1 = steps[0], os1 = steps[1], os2 = steps[2]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + for (i = 0; i < n; ++i, ip1 += is1, op1 += os1, op2 += os2) /** (ip1, ip2) -> (op1) */ -#define BINARY_LOOP\ - char *ip1 = args[0], *ip2 = args[1], *op1 = args[2];\ - npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];\ - npy_intp n = dimensions[0];\ - npy_intp i;\ - for(i = 0; i < n; ++i, ip1 += is1, ip2 += is2, op1 += os1) +#define BINARY_LOOP \ + char *ip1 = args[0], *ip2 = args[1], *op1 = args[2]; \ + npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + for (i = 0; i < n; ++i, ip1 += is1, ip2 += is2, op1 += os1) /** (ip1, ip2) -> (op1, op2) */ -#define BINARY_LOOP_TWO_OUT\ - char *ip1 = args[0], *ip2 = args[1], *op1 = args[2], *op2 = args[3];\ - npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2], os2 = steps[3];\ - npy_intp n = dimensions[0];\ - npy_intp i;\ - for(i = 0; i < n; ++i, ip1 += is1, ip2 += is2, op1 += os1, op2 += os2) +#define BINARY_LOOP_TWO_OUT \ + char *ip1 = args[0], *ip2 = args[1], *op1 = args[2], *op2 = args[3]; \ + npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2], os2 = steps[3]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + for (i = 0; i < n; ++i, ip1 += is1, ip2 += is2, op1 += os1, op2 += os2) /** (ip1, ip2, ip3) -> (op1) */ -#define TERNARY_LOOP\ - char *ip1 = args[0], *ip2 = args[1], *ip3 = args[2], *op1 = args[3];\ - npy_intp is1 = steps[0], is2 = steps[1], is3 = steps[2], os1 = steps[3];\ - npy_intp n = dimensions[0];\ - npy_intp i;\ - for(i = 0; i < n; ++i, ip1 += is1, ip2 += is2, ip3 += is3, op1 += os1) +#define TERNARY_LOOP \ + char *ip1 = args[0], *ip2 = args[1], *ip3 = args[2], *op1 = args[3]; \ + npy_intp is1 = steps[0], is2 = steps[1], is3 = steps[2], os1 = steps[3]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + for (i = 0; i < n; ++i, ip1 += is1, ip2 += is2, ip3 += is3, op1 += os1) /** @} */ /* unary loop input and output contiguous */ -#define IS_UNARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \ - steps[1] == sizeof(tout)) +#define IS_UNARY_CONT(tin, tout) \ + (steps[0] == sizeof(tin) && steps[1] == sizeof(tout)) #define IS_OUTPUT_CONT(tout) (steps[1] == sizeof(tout)) -#define IS_BINARY_REDUCE ((args[0] == args[2])\ - && (steps[0] == steps[2])\ - && (steps[0] == 0)) +#define IS_BINARY_REDUCE \ + ((args[0] == args[2]) && (steps[0] == steps[2]) && (steps[0] == 0)) /* binary loop input and output contiguous */ -#define IS_BINARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \ - steps[1] == sizeof(tin) && \ - steps[2] == sizeof(tout)) +#define IS_BINARY_CONT(tin, tout) \ + (steps[0] == sizeof(tin) && steps[1] == sizeof(tin) && \ + steps[2] == sizeof(tout)) /* binary loop input and output contiguous with first scalar */ -#define IS_BINARY_CONT_S1(tin, tout) (steps[0] == 0 && \ - steps[1] == sizeof(tin) && \ - steps[2] == sizeof(tout)) +#define IS_BINARY_CONT_S1(tin, tout) \ + (steps[0] == 0 && steps[1] == sizeof(tin) && steps[2] == sizeof(tout)) /* binary loop input and output contiguous with second scalar */ -#define IS_BINARY_CONT_S2(tin, tout) (steps[0] == sizeof(tin) && \ - steps[1] == 0 && \ - steps[2] == sizeof(tout)) +#define IS_BINARY_CONT_S2(tin, tout) \ + (steps[0] == sizeof(tin) && steps[1] == 0 && steps[2] == sizeof(tout)) /* * loop with contiguous specialization @@ -157,29 +158,26 @@ * combine with NPY_GCC_OPT_3 to allow autovectorization * should only be used where its worthwhile to avoid code bloat */ -#define BASE_UNARY_LOOP(tin, tout, op) \ - UNARY_LOOP { \ - const tin in = *(tin *)ip1; \ - tout *out = (tout *)op1; \ - op; \ - } +#define BASE_UNARY_LOOP(tin, tout, op) \ + UNARY_LOOP { \ + const tin in = *(tin *)ip1; \ + tout *out = (tout *)op1; \ + op; \ + } -#define UNARY_LOOP_FAST(tin, tout, op) \ - do { \ - /* condition allows compiler to optimize the generic macro */ \ - if (IS_UNARY_CONT(tin, tout)) { \ - if (args[0] == args[1]) { \ - BASE_UNARY_LOOP(tin, tout, op) \ - } \ - else { \ - BASE_UNARY_LOOP(tin, tout, op) \ - } \ - } \ - else { \ - BASE_UNARY_LOOP(tin, tout, op) \ - } \ - } \ - while (0) +#define UNARY_LOOP_FAST(tin, tout, op) \ + do { \ + /* condition allows compiler to optimize the generic macro */ \ + if (IS_UNARY_CONT(tin, tout)) { \ + if (args[0] == args[1]) { \ + BASE_UNARY_LOOP(tin, tout, op) \ + } else { \ + BASE_UNARY_LOOP(tin, tout, op) \ + } \ + } else { \ + BASE_UNARY_LOOP(tin, tout, op) \ + } \ + } while (0) /* * loop with contiguous specialization @@ -188,13 +186,13 @@ * combine with NPY_GCC_OPT_3 to allow autovectorization * should only be used where its worthwhile to avoid code bloat */ -#define BASE_BINARY_LOOP(tin, tout, op) \ - BINARY_LOOP { \ - const tin in1 = *(tin *)ip1; \ - const tin in2 = *(tin *)ip2; \ - tout *out = (tout *)op1; \ - op; \ - } +#define BASE_BINARY_LOOP(tin, tout, op) \ + BINARY_LOOP { \ + const tin in1 = *(tin *)ip1; \ + const tin in2 = *(tin *)ip2; \ + tout *out = (tout *)op1; \ + op; \ + } /* * unfortunately gcc 6/7 regressed and we need to give it additional hints to @@ -207,85 +205,76 @@ #else #define IVDEP_LOOP #endif -#define BASE_BINARY_LOOP_INP(tin, tout, op) \ - char *ip1 = args[0], *ip2 = args[1], *op1 = args[2];\ - npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];\ - npy_intp n = dimensions[0];\ - npy_intp i;\ - IVDEP_LOOP \ - for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1) { \ - const tin in1 = *(tin *)ip1; \ - const tin in2 = *(tin *)ip2; \ - tout *out = (tout *)op1; \ - op; \ - } +#define BASE_BINARY_LOOP_INP(tin, tout, op) \ + char *ip1 = args[0], *ip2 = args[1], *op1 = args[2]; \ + npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + IVDEP_LOOP \ + for (i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1) { \ + const tin in1 = *(tin *)ip1; \ + const tin in2 = *(tin *)ip2; \ + tout *out = (tout *)op1; \ + op; \ + } -#define BASE_BINARY_LOOP_S(tin, tout, cin, cinp, vin, vinp, op) \ - const tin cin = *(tin *)cinp; \ - BINARY_LOOP { \ - const tin vin = *(tin *)vinp; \ - tout *out = (tout *)op1; \ - op; \ - } +#define BASE_BINARY_LOOP_S(tin, tout, cin, cinp, vin, vinp, op) \ + const tin cin = *(tin *)cinp; \ + BINARY_LOOP { \ + const tin vin = *(tin *)vinp; \ + tout *out = (tout *)op1; \ + op; \ + } /* PR80198 again, scalar works without the pragma */ -#define BASE_BINARY_LOOP_S_INP(tin, tout, cin, cinp, vin, vinp, op) \ - const tin cin = *(tin *)cinp; \ - BINARY_LOOP { \ - const tin vin = *(tin *)vinp; \ - tout *out = (tout *)vinp; \ - op; \ - } - -#define BINARY_LOOP_FAST(tin, tout, op) \ - do { \ - /* condition allows compiler to optimize the generic macro */ \ - if (IS_BINARY_CONT(tin, tout)) { \ - if (abs_ptrdiff(args[2], args[0]) == 0 && \ - abs_ptrdiff(args[2], args[1]) >= NPY_MAX_SIMD_SIZE) { \ - BASE_BINARY_LOOP_INP(tin, tout, op) \ - } \ - else if (abs_ptrdiff(args[2], args[1]) == 0 && \ - abs_ptrdiff(args[2], args[0]) >= NPY_MAX_SIMD_SIZE) { \ - BASE_BINARY_LOOP_INP(tin, tout, op) \ - } \ - else { \ - BASE_BINARY_LOOP(tin, tout, op) \ - } \ - } \ - else if (IS_BINARY_CONT_S1(tin, tout)) { \ - if (abs_ptrdiff(args[2], args[1]) == 0) { \ - BASE_BINARY_LOOP_S_INP(tin, tout, in1, args[0], in2, ip2, op) \ - } \ - else { \ - BASE_BINARY_LOOP_S(tin, tout, in1, args[0], in2, ip2, op) \ - } \ - } \ - else if (IS_BINARY_CONT_S2(tin, tout)) { \ - if (abs_ptrdiff(args[2], args[0]) == 0) { \ - BASE_BINARY_LOOP_S_INP(tin, tout, in2, args[1], in1, ip1, op) \ - } \ - else { \ - BASE_BINARY_LOOP_S(tin, tout, in2, args[1], in1, ip1, op) \ - }\ - } \ - else { \ - BASE_BINARY_LOOP(tin, tout, op) \ - } \ - } \ - while (0) +#define BASE_BINARY_LOOP_S_INP(tin, tout, cin, cinp, vin, vinp, op) \ + const tin cin = *(tin *)cinp; \ + BINARY_LOOP { \ + const tin vin = *(tin *)vinp; \ + tout *out = (tout *)vinp; \ + op; \ + } -#define BINARY_REDUCE_LOOP_INNER\ - char *ip2 = args[1]; \ - npy_intp is2 = steps[1]; \ - npy_intp n = dimensions[0]; \ - npy_intp i; \ - for(i = 0; i < n; i++, ip2 += is2) +#define BINARY_LOOP_FAST(tin, tout, op) \ + do { \ + /* condition allows compiler to optimize the generic macro */ \ + if (IS_BINARY_CONT(tin, tout)) { \ + if (abs_ptrdiff(args[2], args[0]) == 0 && \ + abs_ptrdiff(args[2], args[1]) >= NPY_MAX_SIMD_SIZE) { \ + BASE_BINARY_LOOP_INP(tin, tout, op) \ + } else if (abs_ptrdiff(args[2], args[1]) == 0 && \ + abs_ptrdiff(args[2], args[0]) >= NPY_MAX_SIMD_SIZE) { \ + BASE_BINARY_LOOP_INP(tin, tout, op) \ + } else { \ + BASE_BINARY_LOOP(tin, tout, op) \ + } \ + } else if (IS_BINARY_CONT_S1(tin, tout)) { \ + if (abs_ptrdiff(args[2], args[1]) == 0) { \ + BASE_BINARY_LOOP_S_INP(tin, tout, in1, args[0], in2, ip2, op) \ + } else { \ + BASE_BINARY_LOOP_S(tin, tout, in1, args[0], in2, ip2, op) \ + } \ + } else if (IS_BINARY_CONT_S2(tin, tout)) { \ + if (abs_ptrdiff(args[2], args[0]) == 0) { \ + BASE_BINARY_LOOP_S_INP(tin, tout, in2, args[1], in1, ip1, op) \ + } else { \ + BASE_BINARY_LOOP_S(tin, tout, in2, args[1], in1, ip1, op) \ + } \ + } else { \ + BASE_BINARY_LOOP(tin, tout, op) \ + } \ + } while (0) -#define BINARY_REDUCE_LOOP(TYPE)\ - char *iop1 = args[0]; \ - TYPE io1 = *(TYPE *)iop1; \ - BINARY_REDUCE_LOOP_INNER +#define BINARY_REDUCE_LOOP_INNER \ + char *ip2 = args[1]; \ + npy_intp is2 = steps[1]; \ + npy_intp n = dimensions[0]; \ + npy_intp i; \ + for (i = 0; i < n; i++, ip2 += is2) +#define BINARY_REDUCE_LOOP(TYPE) \ + char *iop1 = args[0]; \ + TYPE io1 = *(TYPE *)iop1; \ + BINARY_REDUCE_LOOP_INNER #endif /* _NPY_UMATH_FAST_LOOP_MACROS_H_ */ diff --git a/mkl_umath/src/mkl_umath_loops.c.src b/mkl_umath/src/mkl_umath_loops.c.src index 32babc0..b588ca6 100644 --- a/mkl_umath/src/mkl_umath_loops.c.src +++ b/mkl_umath/src/mkl_umath_loops.c.src @@ -44,7 +44,7 @@ // NPY_2_0_API_VERSION 0x00000012 is defined in numpy-2 // inside numpy/_core/include/numpy/numpyconfig.h -#if NPY_API_VERSION >= 0x00000012 +#if NPY_API_VERSION >= 0x00000012 #define USE_NUMPY_2 #endif @@ -158,8 +158,8 @@ static inline npy_float spacingf(npy_float x) { } #if defined(_MSC_VER) && defined(__INTEL_COMPILER) -extern __inline float __cdecl ldexpf( float _X, int _Y) { - return (float)ldexp(_X, _Y); +extern __inline float __cdecl ldexpf( float _X, int _Y) { + return (float)ldexp(_X, _Y); } #endif @@ -228,7 +228,7 @@ divmod@c@(@type@ a, @type@ b, @type@ *modulus) * Float types * #type = npy_float, npy_double# * #TYPE = FLOAT, DOUBLE# - * #c = f, # + * #c = f, # * #s = s, d# */ @@ -356,7 +356,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp for(j = 0; j < j_max; j++) { op1_shifted[j] = ip1_aligned[j] @OP@ ip2_shifted[j]; } - } + } else { NPY_ASSUME_ALIGNED(ip1_aligned, 64) for(j = 0; j < j_max; j++) { @@ -372,12 +372,12 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp op1[i] = ip1[i] @OP@ ip2[i]; } } - } + } else if (IS_BINARY_CONT_S1(@type@, @type@)) { if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same2) { CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[1], args[2], @OP@1.0, *(@type@*)args[0], 0.0, 1.0); /* v@s@LinearFrac(dimensions[0], (@type@*) args[1], (@type@*) args[1], @OP@1.0, *(@type@*)args[0], 0.0, 1.0, (@type@*) args[2]); */ - } + } else { @type@ *ip1 = (@type@*)args[0]; @type@ *ip2 = (@type@*)args[1]; @@ -412,7 +412,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp op1[i] = ip1c @OP@ ip2[i]; } } - } + } else if (IS_BINARY_CONT_S2(@type@, @type@)) { if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same1) { CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[0], args[2], 1.0, @OP@(*(@type@*)args[1]), 0.0, 1.0); @@ -452,7 +452,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp op1[i] = ip1[i] @OP@ ip2c; } } - } + } else if (IS_BINARY_REDUCE) { #if @PW@ @type@ * iop1 = (@type@ *)args[0]; @@ -465,7 +465,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp } *((@type@ *)iop1) = io1; #endif - } + } else { BINARY_LOOP { const @type@ in1 = *(@type@ *)ip1; @@ -515,7 +515,7 @@ mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_int for(j = 0; j < j_max; j++) { op1_shifted[j] = ip1_aligned[j] * ip2_shifted[j]; } - } + } else { NPY_ASSUME_ALIGNED(ip1_aligned, 64) for(j = 0; j < j_max; j++) { @@ -531,7 +531,7 @@ mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_int op1[i] = ip1[i] * ip2[i]; } } - } + } else if (IS_BINARY_CONT_S1(@type@, @type@)) { if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same2) { CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[1], args[2], *(@type@*)args[0], 0.0, 0.0, 1.0); @@ -571,7 +571,7 @@ mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_int op1[i] = ip1c * ip2[i]; } } - } + } else if (IS_BINARY_CONT_S2(@type@, @type@)) { if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same1) { CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[0], args[2], *(@type@*)args[1], 0.0, 0.0, 1.0); @@ -611,13 +611,13 @@ mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_int op1[i] = ip1[i] * ip2c; } } - } + } else if (IS_BINARY_REDUCE) { BINARY_REDUCE_LOOP(@type@) { io1 *= *(@type@ *)ip2; } *((@type@ *)iop1) = io1; - } + } else { BINARY_LOOP { const @type@ in1 = *(@type@ *)ip1; @@ -669,7 +669,7 @@ mkl_umath_@TYPE@_divide(char **args, const npy_intp *dimensions, const npy_intp for(j = 0; j < j_max; j++) { op1_shifted[j] = ip1_aligned[j] / ip2_shifted[j]; } - } + } else { NPY_ASSUME_ALIGNED(ip1_aligned, 64) for(j = 0; j < j_max; j++) { @@ -686,7 +686,7 @@ mkl_umath_@TYPE@_divide(char **args, const npy_intp *dimensions, const npy_intp op1[i] = ip1[i] / ip2[i]; } } - } + } else if (IS_BINARY_CONT_S1(@type@, @type@)) { @type@ *ip1 = (@type@*)args[0]; @type@ *ip2 = (@type@*)args[1]; @@ -721,7 +721,7 @@ mkl_umath_@TYPE@_divide(char **args, const npy_intp *dimensions, const npy_intp for(; i < n; i++) { op1[i] = ip1c / ip2[i]; } - } + } else if (IS_BINARY_CONT_S2(@type@, @type@)) { @type@ *ip1 = (@type@*)args[0]; @type@ *ip2 = (@type@*)args[1]; @@ -756,13 +756,13 @@ mkl_umath_@TYPE@_divide(char **args, const npy_intp *dimensions, const npy_intp for(; i < n; i++) { op1[i] = ip1[i] / ip2c; } - } + } else if (IS_BINARY_REDUCE) { BINARY_REDUCE_LOOP(@type@) { io1 /= *(@type@ *)ip2; } *((@type@ *)iop1) = io1; - } + } else { BINARY_LOOP { const @type@ in1 = *(@type@ *)ip1; @@ -884,7 +884,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp ignore_fpstatus = 1; CHUNKED_VML_CALL2(v@s@@VML@, dimensions[0], @type@, @type@, @type@, args[0], args[1]); /* v@s@Exp(dimensions[0], (@type@*) args[0], (@type@*) args[1]); */ - } + } else { UNARY_LOOP_DISPATCH( @type@, @type@ @@ -1193,7 +1193,7 @@ mkl_umath_@TYPE@_ldexp_long(char **args, const npy_intp *dimensions, const npy_i * #mkl_type = MKL_Complex8, MKL_Complex16# * #mkl_ftype = float, double# * #c = f, # - * #C = F, # + * #C = F, # * #s = c, z# */ @@ -1280,7 +1280,7 @@ pairwise_sum_@TYPE@(@ftype@ *rr, @ftype@ * ri, char * a, npy_intp n, npy_intp st * #kind = add, subtract# * #OP = +, -# * #PW = 1, 0# - * #VML = Add, Sub# + * #VML = Add, Sub# */ void mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func)) @@ -1294,7 +1294,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp CHUNKED_VML_CALL3(v@s@@VML@, dimensions[0], @type@, @mkl_type@, args[0], args[1], args[2]); /* v@s@@VML@(dimensions[0], (@mkl_type@*) args[0], (@mkl_type@*) args[1], (@mkl_type@*) args[2]); */ } - else { + else { if (IS_BINARY_REDUCE && @PW@) { npy_intp n = dimensions[0]; @ftype@ * or = ((@ftype@ *)args[0]); @@ -1305,7 +1305,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp *or @OP@= rr; *oi @OP@= ri; return; - } + } else { BINARY_LOOP { const @ftype@ in1r = ((@ftype@ *)ip1)[0]; @@ -1350,13 +1350,13 @@ mkl_umath_@TYPE@_divide(char **args, const npy_intp *dimensions, const npy_intp const int contig = IS_BINARY_CONT(@mkl_type@, @mkl_type@); const int disjoint_or_same1 = DISJOINT_OR_SAME(args[0], args[2], dimensions[0], sizeof(@type@)); const int disjoint_or_same2 = DISJOINT_OR_SAME(args[1], args[2], dimensions[0], sizeof(@type@)); - const int can_vectorize = contig && disjoint_or_same1 && disjoint_or_same2; + const int can_vectorize = contig && disjoint_or_same1 && disjoint_or_same2; if (can_vectorize && dimensions[0] > VML_D_THRESHOLD) { CHUNKED_VML_CALL3(v@s@Div, dimensions[0], @type@, @mkl_type@, args[0], args[1], args[2]); /* v@s@Div(dimensions[0], (@mkl_type@*) args[0], (@mkl_type@*) args[1], (@mkl_type@*) args[2]); */ } - else { + else { BINARY_LOOP { const @ftype@ in1r = ((@ftype@ *)ip1)[0]; const @ftype@ in1i = ((@ftype@ *)ip1)[1]; @@ -1485,7 +1485,7 @@ mkl_umath_@TYPE@_reciprocal(char **args, const npy_intp *dimensions, const npy_i const @ftype@ d = in1r + in1i*r; ((@ftype@ *)op1)[0] = 1/d; ((@ftype@ *)op1)[1] = -r/d; - } + } else { const @ftype@ r = in1r/in1i; const @ftype@ d = in1r*r + in1i; @@ -1504,7 +1504,7 @@ mkl_umath_@TYPE@_conjugate(char **args, const npy_intp *dimensions, const npy_in if (can_vectorize && dimensions[0] > VML_TRANSCEDENTAL_THRESHOLD) { CHUNKED_VML_CALL2(v@s@Conj, dimensions[0], @type@, @mkl_type@, @mkl_type@, args[0], args[1]); /* v@s@Conj(dimensions[0], (@mkl_type@*) args[0], (@mkl_type@*) args[1]); */ - } + } else { UNARY_LOOP { const @ftype@ in1r = ((@ftype@ *)ip1)[0]; @@ -1531,12 +1531,12 @@ mkl_umath_@TYPE@_absolute(char **args, const npy_intp *dimensions, const npy_int const int disjoint_or_same = DISJOINT_OR_SAME_TWO_DTYPES(args[0], args[1], dimensions[0], sizeof(@type@), sizeof(@ftype@)); const int can_vectorize = contig && disjoint_or_same; int ignore_fpstatus = 0; - + if (can_vectorize && dimensions[0] > VML_TRANSCEDENTAL_THRESHOLD) { ignore_fpstatus = 1; CHUNKED_VML_CALL2(v@s@Abs, dimensions[0], @type@, @mkl_type@, @mkl_ftype@, args[0], args[1]); /* v@s@Abs(dimensions[0], (@mkl_type@*) args[0], (@mkl_ftype@*) args[1]); */ - } + } else { UNARY_LOOP { const @ftype@ in1r = ((@ftype@ *)ip1)[0]; diff --git a/mkl_umath/src/mkl_umath_loops.h.src b/mkl_umath/src/mkl_umath_loops.h.src index 714c877..087a97c 100644 --- a/mkl_umath/src/mkl_umath_loops.h.src +++ b/mkl_umath/src/mkl_umath_loops.h.src @@ -44,7 +44,7 @@ // NPY_2_0_API_VERSION 0x00000012 is defined in numpy-2 // inside numpy/_core/include/numpy/numpyconfig.h -#if NPY_API_VERSION >= 0x00000012 +#if NPY_API_VERSION >= 0x00000012 #define USE_NUMPY_2 #endif @@ -54,10 +54,10 @@ */ /**begin repeat1 - * # kind = absolute, add, arccos, arccosh, arcsin, arcsinh, arctan, arctanh, cbrt, ceil, conjugate, - copysign, cos, cosh, divide, divmod, isfinite, isinf, isnan, equal, exp, exp2, expm1, fabs, - floor, fmax, fmin, frexp, greater, greater_equal, ldexp, less, less_equal, log, log2, log10, - log1p, logical_and, logical_not, logical_or, logical_xor, multiply, modf, + * # kind = absolute, add, arccos, arccosh, arcsin, arcsinh, arctan, arctanh, cbrt, ceil, conjugate, + copysign, cos, cosh, divide, divmod, isfinite, isinf, isnan, equal, exp, exp2, expm1, fabs, + floor, fmax, fmin, frexp, greater, greater_equal, ldexp, less, less_equal, log, log2, log10, + log1p, logical_and, logical_not, logical_or, logical_xor, multiply, modf, negative, nextafter, not_equal, positive, reciprocal, rint, sign, signbit, sin, sinh, spacing, sqrt, square, subtract, tan, tanh, trunc# */ @@ -97,7 +97,7 @@ mkl_umath_@TYPE@_ldexp_long(char **args, const npy_intp *dimensions, const npy_i */ /**begin repeat1 - * # kind = absolute, add, conjugate, divide, isfinite, isinf, isnan, equal, fmax, fmin, greater, greater_equal, + * # kind = absolute, add, conjugate, divide, isfinite, isinf, isnan, equal, fmax, fmin, greater, greater_equal, less, less_equal, logical_and, logical_not, logical_or, logical_xor, multiply, not_equal, reciprocal, sign, square, subtract# */ diff --git a/mkl_umath/src/ufuncsmodule.c b/mkl_umath/src/ufuncsmodule.c index a74725f..ab29416 100644 --- a/mkl_umath/src/ufuncsmodule.c +++ b/mkl_umath/src/ufuncsmodule.c @@ -15,52 +15,48 @@ * * 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. + * 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. */ + +// clang-format off #include "Python.h" #include "ufuncsmodule.h" +// clang-format on /* now we initialize the Python module which contains our new object: */ static PyModuleDef _ufuncs_module = { - PyModuleDef_HEAD_INIT, - "_ufuncs", - "", - -1, - NULL, NULL, NULL, NULL, NULL -}; + PyModuleDef_HEAD_INIT, "_ufuncs", "", -1, NULL, NULL, NULL, NULL, NULL}; -PyMODINIT_FUNC -PyInit__ufuncs(void) -{ - PyObject* m; - PyObject* d; +PyMODINIT_FUNC PyInit__ufuncs(void) { + PyObject *m; + PyObject *d; - m = PyModule_Create(&_ufuncs_module); - if (m == NULL) - return NULL; + m = PyModule_Create(&_ufuncs_module); + if (m == NULL) + return NULL; - d = PyModule_GetDict(m); - if (d == NULL) { - Py_XDECREF(m); - return NULL; - } + d = PyModule_GetDict(m); + if (d == NULL) { + Py_XDECREF(m); + return NULL; + } - import_array(); - import_umath(); + import_array(); + import_umath(); - if (InitOperators(d) < 0) { - Py_XDECREF(d); - Py_XDECREF(m); - return NULL; - } + if (InitOperators(d) < 0) { + Py_XDECREF(d); + Py_XDECREF(m); + return NULL; + } - return m; + return m; } - diff --git a/mkl_umath/src/ufuncsmodule.h b/mkl_umath/src/ufuncsmodule.h index accef8e..8a8d012 100644 --- a/mkl_umath/src/ufuncsmodule.h +++ b/mkl_umath/src/ufuncsmodule.h @@ -15,15 +15,18 @@ * * 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. + * 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. */ + +// clang-format off #include "Python.h" #define PY_ARRAY_UNIQUE_SYMBOL mkl_umath_ufunc_ext #include "numpy/arrayobject.h" @@ -31,3 +34,4 @@ #include "numpy/ufuncobject.h" #include "__umath_generated.c" +// clang-format on diff --git a/mkl_umath/tests/test_basic.py b/mkl_umath/tests/test_basic.py index 9660662..3fd5a35 100644 --- a/mkl_umath/tests/test_basic.py +++ b/mkl_umath/tests/test_basic.py @@ -23,13 +23,15 @@ # 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. -import pytest import numpy as np -import mkl_umath._ufuncs as mu -import mkl_umath._patch as mp +import pytest + +import mkl_umath._patch as mp # pylint: disable=no-name-in-module +import mkl_umath._ufuncs as mu # pylint: disable=no-name-in-module np.random.seed(42) + def get_args(args_str, size, low, high): args = [] a = np.random.uniform(low, high, size) @@ -46,13 +48,16 @@ def get_args(args_str, size, low, high): elif s == "i": args.append(np.int_(np.random.randint(low=1, high=10))) elif s == "l": - args.append(np.dtype("long").type(np.random.randint(low=1, high=10))) + args.append( + np.dtype("long").type(np.random.randint(low=1, high=10)) + ) elif s == "q": args.append(np.int64(np.random.randint(low=1, high=10))) else: raise ValueError("Unexpected type specified!") return tuple(args) + umaths = [i for i in dir(mu) if isinstance(getattr(mu, i), np.ufunc)] mkl_cases = {} @@ -62,41 +67,47 @@ def get_args(args_str, size, low, high): types = mkl_umath.types size_mkl = 8192 + 1 for type_ in types: - args_str = type_[:type_.find("->")] + args_str = type_[: type_.find("->")] if umath in ["arccos", "arcsin", "arctanh"]: - low = -1; high = 1 + low = -1 + high = 1 elif umath in ["log", "log10", "log1p", "log2", "sqrt"]: - low = 0; high = 10 + low = 0 + high = 10 elif umath == "arccosh": - low = 1; high = 10 + low = 1 + high = 10 else: - low = -10; high = 10 - + low = -10 + high = 10 + if umath in ["add", "subtract", "multiply"]: size_mkl = 10**5 + 1 - # when size > size_mkl, mkl is used (if supported), + # when size > size_mkl, mkl is used (if supported), # otherwise it falls back on numpy algorithm args_mkl = get_args(args_str, size_mkl, low, high) args_fall_back = get_args(args_str, 100, low, high) mkl_cases[(umath, type_)] = args_mkl - fall_back_cases[(umath, type_)] = args_fall_back + fall_back_cases[(umath, type_)] = args_fall_back test_mkl = {**mkl_cases} test_fall_back = {**fall_back_cases} + def get_id(val): return val.__str__() + @pytest.mark.parametrize("case", test_mkl, ids=get_id) def test_mkl_umath(case): umath, _ = case args = test_mkl[case] mkl_umath = getattr(mu, umath) np_umath = getattr(np, umath) - + mkl_res = mkl_umath(*args) np_res = np_umath(*args) - + assert np.allclose(mkl_res, np_res), f"Results for '{umath}' do not match" @@ -106,11 +117,11 @@ def test_fall_back_umath(case): args = test_fall_back[case] mkl_umath = getattr(mu, umath) np_umath = getattr(np, umath) - + mkl_res = mkl_umath(*args) np_res = np_umath(*args) - assert np.allclose(mkl_res, np_res), f"Results for '{umath}' do not match" + assert np.allclose(mkl_res, np_res), f"Results for '{umath}' do not match" @pytest.mark.parametrize("func", ["add", "subtract", "multiply", "divide"]) @@ -122,12 +133,16 @@ def test_scalar(func, size, dtype): # testing implementation in IS_BINARY_CONT_S1 branch mkl_res = getattr(mu, func)(a, 1.0) np_res = getattr(np, func)(a, 1.0) - assert np.allclose(mkl_res, np_res), f"Results for '{func}(array, scalar)' do not match" + assert np.allclose( + mkl_res, np_res + ), f"Results for '{func}(array, scalar)' do not match" # testing implementation in IS_BINARY_CONT_S2 branch mkl_res = getattr(mu, func)(1.0, a) np_res = getattr(np, func)(1.0, a) - assert np.allclose(mkl_res, np_res), f"Results for '{func}(scalar, array)' do not match" + assert np.allclose( + mkl_res, np_res + ), f"Results for '{func}(scalar, array)' do not match" @pytest.mark.parametrize("func", ["add", "subtract", "multiply", "divide"]) @@ -139,10 +154,14 @@ def test_strided(func, dtype): mkl_res = getattr(mu, func)(a, b) np_res = getattr(np, func)(a, b) - assert np.allclose(mkl_res, np_res), f"Results for '{func}[strided]' do not match" + assert np.allclose( + mkl_res, np_res + ), f"Results for '{func}[strided]' do not match" -@pytest.mark.parametrize("func", ["add", "subtract", "multiply", "divide", "fmax", "fmin"]) +@pytest.mark.parametrize( + "func", ["add", "subtract", "multiply", "divide", "fmax", "fmin"] +) @pytest.mark.parametrize("dtype", [np.float32, np.float64]) def test_reduce_float(func, dtype): # testing implementation in IS_BINARY_REDUCE branch @@ -152,7 +171,9 @@ def test_reduce_float(func, dtype): mkl_res = mkl_func.reduce(a) np_res = np_func.reduce(a) - assert np.allclose(mkl_res, np_res), f"Results for '{func}[reduce]' do not match" + assert np.allclose( + mkl_res, np_res + ), f"Results for '{func}[reduce]' do not match" @pytest.mark.parametrize("func", ["add", "subtract"]) @@ -166,7 +187,9 @@ def test_reduce_complex(func, dtype): mkl_res = mkl_func.reduce(a) np_res = np_func.reduce(a) - assert np.allclose(mkl_res, np_res), f"Results for '{func}[reduce]' do not match" + assert np.allclose( + mkl_res, np_res + ), f"Results for '{func}[reduce]' do not match" def test_patch(): diff --git a/mkl_umath/ufunc_docstrings_numpy1.py b/mkl_umath/ufunc_docstrings_numpy1.py index 57c4fea..39efaee 100644 --- a/mkl_umath/ufunc_docstrings_numpy1.py +++ b/mkl_umath/ufunc_docstrings_numpy1.py @@ -23,7 +23,7 @@ # 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. -# Adapted with minor modifications (numpy.core.* is change to numpy._core.*) from +# Adapted with modifications (numpy.core.* is change to numpy._core.*) from # https://github.com/numpy/numpy/blob/maintenance/1.26.x/numpy/core/code_generators/ufunc_docstrings.py """ @@ -37,13 +37,14 @@ ufuncs are created at compile time. """ + import textwrap docdict = {} # common parameter text to all ufuncs subst = { - 'PARAMS': textwrap.dedent(""" + "PARAMS": textwrap.dedent(""" out : ndarray, None, or tuple of ndarray and None, optional A location into which the result is stored. If provided, it must have a shape that the inputs broadcast to. If not provided or None, @@ -60,37 +61,42 @@ For other keyword-only arguments, see the :ref:`ufunc docs `. """).strip(), - 'BROADCASTABLE_2': ("If ``x1.shape != x2.shape``, they must be " - "broadcastable to a common\n shape (which becomes " - "the shape of the output)."), - 'OUT_SCALAR_1': "This is a scalar if `x` is a scalar.", - 'OUT_SCALAR_2': "This is a scalar if both `x1` and `x2` are scalars.", + "BROADCASTABLE_2": ( + "If ``x1.shape != x2.shape``, they must be " + "broadcastable to a common\n shape (which becomes " + "the shape of the output)." + ), + "OUT_SCALAR_1": "This is a scalar if `x` is a scalar.", + "OUT_SCALAR_2": "This is a scalar if both `x1` and `x2` are scalars.", } + def add_newdoc(place, name, doc): doc = textwrap.dedent(doc).strip() skip = ( # gufuncs do not use the OUT_SCALAR replacement strings - 'matmul', + "matmul", # clip has 3 inputs, which is not handled by this - 'clip', + "clip", ) - if name[0] != '_' and name not in skip: - if '\nx :' in doc: - assert '$OUT_SCALAR_1' in doc, "in {}".format(name) - elif '\nx2 :' in doc or '\nx1, x2 :' in doc: - assert '$OUT_SCALAR_2' in doc, "in {}".format(name) + if name[0] != "_" and name not in skip: + if "\nx :" in doc: + assert "$OUT_SCALAR_1" in doc, "in {}".format(name) + elif "\nx2 :" in doc or "\nx1, x2 :" in doc: + assert "$OUT_SCALAR_2" in doc, "in {}".format(name) else: - assert False, "Could not detect number of inputs in {}".format(name) + raise AssertionError(f"Could not detect number of inputs in {name}") for k, v in subst.items(): - doc = doc.replace('$' + k, v) + doc = doc.replace("$" + k, v) - docdict['.'.join((place, name))] = doc + docdict[".".join((place, name))] = doc -add_newdoc('numpy._core.umath', 'absolute', +add_newdoc( + "numpy._core.umath", + "absolute", """ Calculate the absolute value element-wise. @@ -139,9 +145,12 @@ def add_newdoc(place, name, doc): >>> abs(x) array([1.2, 1.2]) - """) + """, +) -add_newdoc('numpy._core.umath', 'add', +add_newdoc( + "numpy._core.umath", + "add", """ Add arguments element-wise. @@ -181,9 +190,12 @@ def add_newdoc(place, name, doc): array([[ 0., 2., 4.], [ 3., 5., 7.], [ 6., 8., 10.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'arccos', +add_newdoc( + "numpy._core.umath", + "arccos", """ Trigonometric inverse cosine, element-wise. @@ -244,9 +256,12 @@ def add_newdoc(place, name, doc): >>> plt.axis('tight') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'arccosh', +add_newdoc( + "numpy._core.umath", + "arccosh", """ Inverse hyperbolic cosine, element-wise. @@ -296,9 +311,12 @@ def add_newdoc(place, name, doc): >>> np.arccosh(1) 0.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'arcsin', +add_newdoc( + "numpy._core.umath", + "arcsin", """ Inverse sine, element-wise. @@ -350,9 +368,12 @@ def add_newdoc(place, name, doc): >>> np.arcsin(0) 0.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'arcsinh', +add_newdoc( + "numpy._core.umath", + "arcsinh", """ Inverse hyperbolic sine element-wise. @@ -397,9 +418,12 @@ def add_newdoc(place, name, doc): >>> np.arcsinh(np.array([np.e, 10.0])) array([ 1.72538256, 2.99822295]) - """) + """, +) -add_newdoc('numpy._core.umath', 'arctan', +add_newdoc( + "numpy._core.umath", + "arctan", """ Trigonometric inverse tangent, element-wise. @@ -463,9 +487,12 @@ def add_newdoc(place, name, doc): >>> plt.axis('tight') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'arctan2', +add_newdoc( + "numpy._core.umath", + "arctan2", """ Element-wise arc tangent of ``x1/x2`` choosing the quadrant correctly. @@ -542,14 +569,20 @@ def add_newdoc(place, name, doc): >>> np.arctan2([0., 0., np.inf], [+0., -0., np.inf]) array([0. , 3.14159265, 0.78539816]) - """) + """, +) -add_newdoc('numpy._core.umath', '_arg', +add_newdoc( + "numpy._core.umath", + "_arg", """ DO NOT USE, ONLY FOR TESTING - """) + """, +) -add_newdoc('numpy._core.umath', 'arctanh', +add_newdoc( + "numpy._core.umath", + "arctanh", """ Inverse hyperbolic tangent element-wise. @@ -598,9 +631,12 @@ def add_newdoc(place, name, doc): >>> np.arctanh([0, -0.5]) array([ 0. , -0.54930614]) - """) + """, +) -add_newdoc('numpy._core.umath', 'bitwise_and', +add_newdoc( + "numpy._core.umath", + "bitwise_and", """ Compute the bit-wise AND of two arrays element-wise. @@ -660,9 +696,12 @@ def add_newdoc(place, name, doc): >>> x1 & x2 array([ 2, 4, 16]) - """) + """, +) -add_newdoc('numpy._core.umath', 'bitwise_or', +add_newdoc( + "numpy._core.umath", + "bitwise_or", """ Compute the bit-wise OR of two arrays element-wise. @@ -727,9 +766,12 @@ def add_newdoc(place, name, doc): >>> x1 | x2 array([ 6, 5, 255]) - """) + """, +) -add_newdoc('numpy._core.umath', 'bitwise_xor', +add_newdoc( + "numpy._core.umath", + "bitwise_xor", """ Compute the bit-wise XOR of two arrays element-wise. @@ -787,9 +829,12 @@ def add_newdoc(place, name, doc): >>> x1 ^ x2 array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'ceil', +add_newdoc( + "numpy._core.umath", + "ceil", """ Return the ceiling of the input, element-wise. @@ -818,9 +863,12 @@ def add_newdoc(place, name, doc): >>> np.ceil(a) array([-1., -1., -0., 1., 2., 2., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'trunc', +add_newdoc( + "numpy._core.umath", + "trunc", """ Return the truncated value of the input, element-wise. @@ -854,9 +902,12 @@ def add_newdoc(place, name, doc): >>> np.trunc(a) array([-1., -1., -0., 0., 1., 1., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'conjugate', +add_newdoc( + "numpy._core.umath", + "conjugate", """ Return the complex conjugate, element-wise. @@ -892,9 +943,12 @@ def add_newdoc(place, name, doc): array([[ 1.-1.j, 0.-0.j], [ 0.-0.j, 1.-1.j]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'cos', +add_newdoc( + "numpy._core.umath", + "cos", """ Cosine element-wise. @@ -937,9 +991,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'cosh', +add_newdoc( + "numpy._core.umath", + "cosh", """ Hyperbolic cosine, element-wise. @@ -969,9 +1026,12 @@ def add_newdoc(place, name, doc): >>> plt.plot(x, np.cosh(x)) >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'degrees', +add_newdoc( + "numpy._core.umath", + "degrees", """ Convert angles from radians to degrees. @@ -1006,9 +1066,12 @@ def add_newdoc(place, name, doc): >>> np.all(r == out) True - """) + """, +) -add_newdoc('numpy._core.umath', 'rad2deg', +add_newdoc( + "numpy._core.umath", + "rad2deg", """ Convert angles from radians to degrees. @@ -1040,9 +1103,12 @@ def add_newdoc(place, name, doc): >>> np.rad2deg(np.pi/2) 90.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'heaviside', +add_newdoc( + "numpy._core.umath", + "heaviside", """ Compute the Heaviside step function. @@ -1084,9 +1150,12 @@ def add_newdoc(place, name, doc): array([ 0. , 0.5, 1. ]) >>> np.heaviside([-1.5, 0, 2.0], 1) array([ 0., 1., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'divide', +add_newdoc( + "numpy._core.umath", + "divide", """ Divide arguments element-wise. @@ -1138,9 +1207,12 @@ def add_newdoc(place, name, doc): [1.5, 2. , 2.5], [3. , 3.5, 4. ]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'equal', +add_newdoc( + "numpy._core.umath", + "equal", """ Return (x1 == x2) element-wise. @@ -1181,9 +1253,12 @@ def add_newdoc(place, name, doc): >>> a == b array([ True, True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'exp', +add_newdoc( + "numpy._core.umath", + "exp", """ Calculate the exponential of all elements in the input array. @@ -1246,9 +1321,12 @@ def add_newdoc(place, name, doc): >>> plt.title('Phase (angle) of exp(x)') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'exp2', +add_newdoc( + "numpy._core.umath", + "exp2", """ Calculate `2**p` for all `p` in the input array. @@ -1279,9 +1357,12 @@ def add_newdoc(place, name, doc): >>> np.exp2([2, 3]) array([ 4., 8.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'expm1', +add_newdoc( + "numpy._core.umath", + "expm1", """ Calculate ``exp(x) - 1`` for all elements in the array. @@ -1318,9 +1399,12 @@ def add_newdoc(place, name, doc): >>> np.exp(1e-10) - 1 1.000000082740371e-10 - """) + """, +) -add_newdoc('numpy._core.umath', 'fabs', +add_newdoc( + "numpy._core.umath", + "fabs", """ Compute the absolute values element-wise. @@ -1352,9 +1436,12 @@ def add_newdoc(place, name, doc): >>> np.fabs([-1.2, 1.2]) array([ 1.2, 1.2]) - """) + """, +) -add_newdoc('numpy._core.umath', 'floor', +add_newdoc( + "numpy._core.umath", + "floor", """ Return the floor of the input, element-wise. @@ -1390,9 +1477,12 @@ def add_newdoc(place, name, doc): >>> np.floor(a) array([-2., -2., -1., 0., 1., 1., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'floor_divide', +add_newdoc( + "numpy._core.umath", + "floor_divide", """ Return the largest integer smaller or equal to the division of the inputs. It is equivalent to the Python ``//`` operator and pairs with the @@ -1436,9 +1526,12 @@ def add_newdoc(place, name, doc): >>> x1 // 2.5 array([0., 0., 1., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'fmod', +add_newdoc( + "numpy._core.umath", + "fmod", """ Returns the element-wise remainder of division. @@ -1494,9 +1587,12 @@ def add_newdoc(place, name, doc): [-1, 0], [ 1, 0]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'greater', +add_newdoc( + "numpy._core.umath", + "greater", """ Return the truth value of (x1 > x2) element-wise. @@ -1532,9 +1628,12 @@ def add_newdoc(place, name, doc): >>> a > b array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'greater_equal', +add_newdoc( + "numpy._core.umath", + "greater_equal", """ Return the truth value of (x1 >= x2) element-wise. @@ -1569,9 +1668,12 @@ def add_newdoc(place, name, doc): >>> a >= b array([ True, True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'hypot', +add_newdoc( + "numpy._core.umath", + "hypot", """ Given the "legs" of a right triangle, return its hypotenuse. @@ -1607,9 +1709,12 @@ def add_newdoc(place, name, doc): [ 5., 5., 5.], [ 5., 5., 5.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'invert', +add_newdoc( + "numpy._core.umath", + "invert", """ Compute bit-wise inversion, or bit-wise NOT, element-wise. @@ -1694,9 +1799,12 @@ def add_newdoc(place, name, doc): >>> ~x1 array([False, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isfinite', +add_newdoc( + "numpy._core.umath", + "isfinite", """ Test element-wise for finiteness (not infinity and not Not a Number). @@ -1753,9 +1861,12 @@ def add_newdoc(place, name, doc): >>> y array([0, 1, 0]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isinf', +add_newdoc( + "numpy._core.umath", + "isinf", """ Test element-wise for positive or negative infinity. @@ -1805,9 +1916,12 @@ def add_newdoc(place, name, doc): >>> y array([1, 0, 1]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isnan', +add_newdoc( + "numpy._core.umath", + "isnan", """ Test element-wise for NaN and return result as a boolean array. @@ -1841,9 +1955,12 @@ def add_newdoc(place, name, doc): >>> np.isnan([np.log(-1.),1.,np.log(0)]) array([ True, False, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isnat', +add_newdoc( + "numpy._core.umath", + "isnat", """ Test element-wise for NaT (not a time) and return result as a boolean array. @@ -1874,9 +1991,12 @@ def add_newdoc(place, name, doc): >>> np.isnat(np.array(["NaT", "2016-01-01"], dtype="datetime64[ns]")) array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'left_shift', +add_newdoc( + "numpy._core.umath", + "left_shift", """ Shift the bits of an integer to the left. @@ -1936,9 +2056,12 @@ def add_newdoc(place, name, doc): >>> x1 << x2 array([10, 20, 40]) - """) + """, +) -add_newdoc('numpy._core.umath', 'less', +add_newdoc( + "numpy._core.umath", + "less", """ Return the truth value of (x1 < x2) element-wise. @@ -1972,9 +2095,12 @@ def add_newdoc(place, name, doc): >>> a < b array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'less_equal', +add_newdoc( + "numpy._core.umath", + "less_equal", """ Return the truth value of (x1 <= x2) element-wise. @@ -2009,9 +2135,12 @@ def add_newdoc(place, name, doc): >>> a <= b array([False, True, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'log', +add_newdoc( + "numpy._core.umath", + "log", """ Natural logarithm, element-wise. @@ -2066,9 +2195,12 @@ def add_newdoc(place, name, doc): >>> np.log([1, np.e, np.e**2, 0]) array([ 0., 1., 2., -Inf]) - """) + """, +) -add_newdoc('numpy._core.umath', 'log10', +add_newdoc( + "numpy._core.umath", + "log10", """ Return the base 10 logarithm of the input array, element-wise. @@ -2120,9 +2252,12 @@ def add_newdoc(place, name, doc): >>> np.log10([1e-15, -3.]) array([-15., nan]) - """) + """, +) -add_newdoc('numpy._core.umath', 'log2', +add_newdoc( + "numpy._core.umath", + "log2", """ Base-2 logarithm of `x`. @@ -2173,9 +2308,12 @@ def add_newdoc(place, name, doc): >>> np.log2(xi) array([ 0.+2.26618007j, 0.+0.j , 1.+0.j , 2.+2.26618007j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logaddexp', +add_newdoc( + "numpy._core.umath", + "logaddexp", """ Logarithm of the sum of exponentiations of the inputs. @@ -2216,9 +2354,12 @@ def add_newdoc(place, name, doc): >>> np.exp(prob12) 3.5000000000000057e-50 - """) + """, +) -add_newdoc('numpy._core.umath', 'logaddexp2', +add_newdoc( + "numpy._core.umath", + "logaddexp2", """ Logarithm of the sum of exponentiations of the inputs in base-2. @@ -2259,9 +2400,12 @@ def add_newdoc(place, name, doc): >>> 2**prob12 3.4999999999999914e-50 - """) + """, +) -add_newdoc('numpy._core.umath', 'log1p', +add_newdoc( + "numpy._core.umath", + "log1p", """ Return the natural logarithm of one plus the input array, element-wise. @@ -2315,9 +2459,12 @@ def add_newdoc(place, name, doc): >>> np.log(1 + 1e-99) 0.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_and', +add_newdoc( + "numpy._core.umath", + "logical_and", """ Compute the truth value of x1 AND x2 element-wise. @@ -2360,9 +2507,12 @@ def add_newdoc(place, name, doc): >>> a & b array([False, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_not', +add_newdoc( + "numpy._core.umath", + "logical_not", """ Compute the truth value of NOT x element-wise. @@ -2394,9 +2544,12 @@ def add_newdoc(place, name, doc): >>> np.logical_not(x<3) array([False, False, False, True, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_or', +add_newdoc( + "numpy._core.umath", + "logical_or", """ Compute the truth value of x1 OR x2 element-wise. @@ -2438,9 +2591,12 @@ def add_newdoc(place, name, doc): >>> a | b array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_xor', +add_newdoc( + "numpy._core.umath", + "logical_xor", """ Compute the truth value of x1 XOR x2, element-wise. @@ -2479,9 +2635,12 @@ def add_newdoc(place, name, doc): array([[ True, False], [False, True]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'maximum', +add_newdoc( + "numpy._core.umath", + "maximum", """ Element-wise maximum of array elements. @@ -2538,9 +2697,12 @@ def add_newdoc(place, name, doc): >>> np.maximum(np.Inf, 1) inf - """) + """, +) -add_newdoc('numpy._core.umath', 'minimum', +add_newdoc( + "numpy._core.umath", + "minimum", """ Element-wise minimum of array elements. @@ -2597,9 +2759,12 @@ def add_newdoc(place, name, doc): >>> np.minimum(-np.Inf, 1) -inf - """) + """, +) -add_newdoc('numpy._core.umath', 'fmax', +add_newdoc( + "numpy._core.umath", + "fmax", """ Element-wise maximum of array elements. @@ -2655,9 +2820,12 @@ def add_newdoc(place, name, doc): >>> np.fmax([np.nan, 0, np.nan],[0, np.nan, np.nan]) array([ 0., 0., nan]) - """) + """, +) -add_newdoc('numpy._core.umath', 'fmin', +add_newdoc( + "numpy._core.umath", + "fmin", """ Element-wise minimum of array elements. @@ -2713,9 +2881,12 @@ def add_newdoc(place, name, doc): >>> np.fmin([np.nan, 0, np.nan],[0, np.nan, np.nan]) array([ 0., 0., nan]) - """) + """, +) -add_newdoc('numpy._core.umath', 'clip', +add_newdoc( + "numpy._core.umath", + "clip", """ Clip (limit) the values in an array. @@ -2753,9 +2924,12 @@ def add_newdoc(place, name, doc): An array with the elements of `a`, but where values < `a_min` are replaced with `a_min`, and those > `a_max` with `a_max`. - """) + """, +) -add_newdoc('numpy._core.umath', 'matmul', +add_newdoc( + "numpy._core.umath", + "matmul", """ Matrix product of two arrays. @@ -2886,9 +3060,12 @@ def add_newdoc(place, name, doc): (-13+0j) .. versionadded:: 1.10.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'modf', +add_newdoc( + "numpy._core.umath", + "modf", """ Return the fractional and integral parts of an array, element-wise. @@ -2926,9 +3103,12 @@ def add_newdoc(place, name, doc): >>> np.modf(-0.5) (-0.5, -0) - """) + """, +) -add_newdoc('numpy._core.umath', 'multiply', +add_newdoc( + "numpy._core.umath", + "multiply", """ Multiply arguments element-wise. @@ -2971,9 +3151,12 @@ def add_newdoc(place, name, doc): [ 0., 4., 10.], [ 0., 7., 16.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'negative', +add_newdoc( + "numpy._core.umath", + "negative", """ Numerical negative, element-wise. @@ -3001,9 +3184,12 @@ def add_newdoc(place, name, doc): >>> -x1 array([-1., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'positive', +add_newdoc( + "numpy._core.umath", + "positive", """ Numerical positive, element-wise. @@ -3039,9 +3225,12 @@ def add_newdoc(place, name, doc): >>> +x1 array([ 1., -1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'not_equal', +add_newdoc( + "numpy._core.umath", + "not_equal", """ Return (x1 != x2) element-wise. @@ -3080,9 +3269,12 @@ def add_newdoc(place, name, doc): array([False, True]) - """) + """, +) -add_newdoc('numpy._core.umath', '_ones_like', +add_newdoc( + "numpy._core.umath", + "_ones_like", """ This function used to be the numpy.ones_like, but now a specific function for that has been written for consistency with the other @@ -3092,9 +3284,12 @@ def add_newdoc(place, name, doc): -------- ones_like - """) + """, +) -add_newdoc('numpy._core.umath', 'power', +add_newdoc( + "numpy._core.umath", + "power", """ First array elements raised to powers from second array, element-wise. @@ -3176,9 +3371,12 @@ def add_newdoc(place, name, doc): >>> np.power(x3, 1.5, dtype=complex) array([-1.83697020e-16-1.j, -1.46957616e-15-8.j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'float_power', +add_newdoc( + "numpy._core.umath", + "float_power", """ First array elements raised to powers from second array, element-wise. @@ -3255,9 +3453,12 @@ def add_newdoc(place, name, doc): >>> np.float_power(x3, 1.5, dtype=complex) array([-1.83697020e-16-1.j, -1.46957616e-15-8.j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'radians', +add_newdoc( + "numpy._core.umath", + "radians", """ Convert angles from degrees to radians. @@ -3292,9 +3493,12 @@ def add_newdoc(place, name, doc): >>> ret is out True - """) + """, +) -add_newdoc('numpy._core.umath', 'deg2rad', +add_newdoc( + "numpy._core.umath", + "deg2rad", """ Convert angles from degrees to radians. @@ -3326,9 +3530,12 @@ def add_newdoc(place, name, doc): >>> np.deg2rad(180) 3.1415926535897931 - """) + """, +) -add_newdoc('numpy._core.umath', 'reciprocal', +add_newdoc( + "numpy._core.umath", + "reciprocal", """ Return the reciprocal of the argument, element-wise. @@ -3362,9 +3569,12 @@ def add_newdoc(place, name, doc): >>> np.reciprocal([1, 2., 3.33]) array([ 1. , 0.5 , 0.3003003]) - """) + """, +) -add_newdoc('numpy._core.umath', 'remainder', +add_newdoc( + "numpy._core.umath", + "remainder", """ Returns the element-wise remainder of division. @@ -3425,9 +3635,12 @@ def add_newdoc(place, name, doc): >>> x1 % 5 array([0, 1, 2, 3, 4, 0, 1]) - """) + """, +) -add_newdoc('numpy._core.umath', 'divmod', +add_newdoc( + "numpy._core.umath", + "divmod", """ Return element-wise quotient and remainder simultaneously. @@ -3474,9 +3687,12 @@ def add_newdoc(place, name, doc): >>> divmod(x, 3) (array([0, 0, 0, 1, 1]), array([0, 1, 2, 0, 1])) - """) + """, +) -add_newdoc('numpy._core.umath', 'right_shift', +add_newdoc( + "numpy._core.umath", + "right_shift", """ Shift the bits of an integer to the right. @@ -3525,9 +3741,12 @@ def add_newdoc(place, name, doc): >>> x1 >> x2 array([5, 2, 1]) - """) + """, +) -add_newdoc('numpy._core.umath', 'rint', +add_newdoc( + "numpy._core.umath", + "rint", """ Round elements of the array to the nearest integer. @@ -3559,9 +3778,12 @@ def add_newdoc(place, name, doc): >>> np.rint(a) array([-2., -2., -0., 0., 2., 2., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'sign', +add_newdoc( + "numpy._core.umath", + "sign", """ Returns an element-wise indication of the sign of a number. @@ -3600,9 +3822,12 @@ def add_newdoc(place, name, doc): >>> np.sign(5-2j) (1+0j) - """) + """, +) -add_newdoc('numpy._core.umath', 'signbit', +add_newdoc( + "numpy._core.umath", + "signbit", """ Returns element-wise True where signbit is set (less than zero). @@ -3625,9 +3850,12 @@ def add_newdoc(place, name, doc): >>> np.signbit(np.array([1, -2.3, 2.1])) array([False, True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'copysign', +add_newdoc( + "numpy._core.umath", + "copysign", """ Change the sign of x1 to that of x2, element-wise. @@ -3662,9 +3890,12 @@ def add_newdoc(place, name, doc): >>> np.copysign([-1, 0, 1], np.arange(3)-1) array([-1., 0., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'nextafter', +add_newdoc( + "numpy._core.umath", + "nextafter", """ Return the next floating-point value after x1 towards x2, element-wise. @@ -3691,9 +3922,12 @@ def add_newdoc(place, name, doc): >>> np.nextafter([1, 2], [2, 1]) == [eps + 1, 2 - eps] array([ True, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'spacing', +add_newdoc( + "numpy._core.umath", + "spacing", """ Return the distance between x and the nearest adjacent number. @@ -3723,9 +3957,12 @@ def add_newdoc(place, name, doc): >>> np.spacing(1) == np.finfo(np.float64).eps True - """) + """, +) -add_newdoc('numpy._core.umath', 'sin', +add_newdoc( + "numpy._core.umath", + "sin", """ Trigonometric sine, element-wise. @@ -3781,9 +4018,12 @@ def add_newdoc(place, name, doc): >>> plt.axis('tight') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'sinh', +add_newdoc( + "numpy._core.umath", + "sinh", """ Hyperbolic sine, element-wise. @@ -3834,9 +4074,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'sqrt', +add_newdoc( + "numpy._core.umath", + "sqrt", """ Return the non-negative square-root of an array, element-wise. @@ -3881,9 +4124,12 @@ def add_newdoc(place, name, doc): >>> np.sqrt([4, -1, np.inf]) array([ 2., nan, inf]) - """) + """, +) -add_newdoc('numpy._core.umath', 'cbrt', +add_newdoc( + "numpy._core.umath", + "cbrt", """ Return the cube-root of an array, element-wise. @@ -3909,9 +4155,12 @@ def add_newdoc(place, name, doc): >>> np.cbrt([1,8,27]) array([ 1., 2., 3.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'square', +add_newdoc( + "numpy._core.umath", + "square", """ Return the element-wise square of the input. @@ -3938,9 +4187,12 @@ def add_newdoc(place, name, doc): >>> np.square([-1j, 1]) array([-1.-0.j, 1.+0.j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'subtract', +add_newdoc( + "numpy._core.umath", + "subtract", """ Subtract arguments, element-wise. @@ -3983,9 +4235,12 @@ def add_newdoc(place, name, doc): [3., 3., 3.], [6., 6., 6.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'tan', +add_newdoc( + "numpy._core.umath", + "tan", """ Compute tangent element-wise. @@ -4032,9 +4287,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'tanh', +add_newdoc( + "numpy._core.umath", + "tanh", """ Compute hyperbolic tangent element-wise. @@ -4084,9 +4342,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'frexp', +add_newdoc( + "numpy._core.umath", + "frexp", """ Decompose the elements of x into mantissa and twos exponent. @@ -4133,9 +4394,12 @@ def add_newdoc(place, name, doc): >>> y1 * 2**y2 array([ 0., 1., 2., 3., 4., 5., 6., 7., 8.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'ldexp', +add_newdoc( + "numpy._core.umath", + "ldexp", """ Returns x1 * 2**x2, element-wise. @@ -4177,9 +4441,12 @@ def add_newdoc(place, name, doc): >>> np.ldexp(*np.frexp(x)) array([ 0., 1., 2., 3., 4., 5.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'gcd', +add_newdoc( + "numpy._core.umath", + "gcd", """ Returns the greatest common divisor of ``|x1|`` and ``|x2|`` @@ -4208,9 +4475,12 @@ def add_newdoc(place, name, doc): >>> np.gcd(np.arange(6), 20) array([20, 1, 2, 1, 4, 5]) - """) + """, +) -add_newdoc('numpy._core.umath', 'lcm', +add_newdoc( + "numpy._core.umath", + "lcm", """ Returns the lowest common multiple of ``|x1|`` and ``|x2|`` @@ -4241,4 +4511,5 @@ def add_newdoc(place, name, doc): >>> np.lcm(np.arange(6), 20) array([ 0, 20, 20, 60, 20, 20]) - """) + """, +) diff --git a/mkl_umath/ufunc_docstrings_numpy2.py b/mkl_umath/ufunc_docstrings_numpy2.py index 899def7..2817e07 100644 --- a/mkl_umath/ufunc_docstrings_numpy2.py +++ b/mkl_umath/ufunc_docstrings_numpy2.py @@ -23,7 +23,7 @@ # 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. -# Adapted from +# Adapted from # https://github.com/numpy/numpy/blob/maintenance/2.2.x/numpy/_core/code_generators/ufunc_docstrings.py """ @@ -37,13 +37,14 @@ ufuncs are created at compile time. """ + import textwrap docdict = {} # common parameter text to all ufuncs subst = { - 'PARAMS': textwrap.dedent(""" + "PARAMS": textwrap.dedent(""" out : ndarray, None, or tuple of ndarray and None, optional A location into which the result is stored. If provided, it must have a shape that the inputs broadcast to. If not provided or None, @@ -60,37 +61,45 @@ For other keyword-only arguments, see the :ref:`ufunc docs `. """).strip(), - 'BROADCASTABLE_2': ("If ``x1.shape != x2.shape``, they must be " - "broadcastable to a common\n shape (which becomes " - "the shape of the output)."), - 'OUT_SCALAR_1': "This is a scalar if `x` is a scalar.", - 'OUT_SCALAR_2': "This is a scalar if both `x1` and `x2` are scalars.", + "BROADCASTABLE_2": ( + "If ``x1.shape != x2.shape``, they must be " + "broadcastable to a common\n shape (which becomes " + "the shape of the output)." + ), + "OUT_SCALAR_1": "This is a scalar if `x` is a scalar.", + "OUT_SCALAR_2": "This is a scalar if both `x1` and `x2` are scalars.", } + def add_newdoc(place, name, doc): doc = textwrap.dedent(doc).strip() skip = ( # gufuncs do not use the OUT_SCALAR replacement strings - 'matmul', 'vecdot', 'matvec', 'vecmat', + "matmul", + "vecdot", + "matvec", + "vecmat", # clip has 3 inputs, which is not handled by this - 'clip', + "clip", ) - if name[0] != '_' and name not in skip: - if '\nx :' in doc: - assert '$OUT_SCALAR_1' in doc, f"in {name}" - elif '\nx2 :' in doc or '\nx1, x2 :' in doc: - assert '$OUT_SCALAR_2' in doc, f"in {name}" + if name[0] != "_" and name not in skip: + if "\nx :" in doc: + assert "$OUT_SCALAR_1" in doc, f"in {name}" + elif "\nx2 :" in doc or "\nx1, x2 :" in doc: + assert "$OUT_SCALAR_2" in doc, f"in {name}" else: - assert False, f"Could not detect number of inputs in {name}" + raise AssertionError(f"Could not detect number of inputs in {name}") for k, v in subst.items(): - doc = doc.replace('$' + k, v) + doc = doc.replace("$" + k, v) - docdict[f'{place}.{name}'] = doc + docdict[f"{place}.{name}"] = doc -add_newdoc('numpy._core.umath', 'absolute', +add_newdoc( + "numpy._core.umath", + "absolute", """ Calculate the absolute value element-wise. @@ -140,9 +149,12 @@ def add_newdoc(place, name, doc): >>> abs(x) array([1.2, 1.2]) - """) + """, +) -add_newdoc('numpy._core.umath', 'add', +add_newdoc( + "numpy._core.umath", + "add", """ Add arguments element-wise. @@ -183,9 +195,12 @@ def add_newdoc(place, name, doc): array([[ 0., 2., 4.], [ 3., 5., 7.], [ 6., 8., 10.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'arccos', +add_newdoc( + "numpy._core.umath", + "arccos", """ Trigonometric inverse cosine, element-wise. @@ -248,9 +263,12 @@ def add_newdoc(place, name, doc): >>> plt.axis('tight') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'arccosh', +add_newdoc( + "numpy._core.umath", + "arccosh", """ Inverse hyperbolic cosine, element-wise. @@ -301,9 +319,12 @@ def add_newdoc(place, name, doc): >>> np.arccosh(1) 0.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'arcsin', +add_newdoc( + "numpy._core.umath", + "arcsin", """ Inverse sine, element-wise. @@ -356,9 +377,12 @@ def add_newdoc(place, name, doc): >>> np.arcsin(0) 0.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'arcsinh', +add_newdoc( + "numpy._core.umath", + "arcsinh", """ Inverse hyperbolic sine element-wise. @@ -404,9 +428,12 @@ def add_newdoc(place, name, doc): >>> np.arcsinh(np.array([np.e, 10.0])) array([ 1.72538256, 2.99822295]) - """) + """, +) -add_newdoc('numpy._core.umath', 'arctan', +add_newdoc( + "numpy._core.umath", + "arctan", """ Trigonometric inverse tangent, element-wise. @@ -472,9 +499,12 @@ def add_newdoc(place, name, doc): >>> plt.axis('tight') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'arctan2', +add_newdoc( + "numpy._core.umath", + "arctan2", """ Element-wise arc tangent of ``x1/x2`` choosing the quadrant correctly. @@ -553,14 +583,20 @@ def add_newdoc(place, name, doc): >>> np.arctan2([0., 0., np.inf], [+0., -0., np.inf]) array([0. , 3.14159265, 0.78539816]) - """) + """, +) -add_newdoc('numpy._core.umath', '_arg', +add_newdoc( + "numpy._core.umath", + "_arg", """ DO NOT USE, ONLY FOR TESTING - """) + """, +) -add_newdoc('numpy._core.umath', 'arctanh', +add_newdoc( + "numpy._core.umath", + "arctanh", """ Inverse hyperbolic tangent element-wise. @@ -610,9 +646,12 @@ def add_newdoc(place, name, doc): >>> np.arctanh([0, -0.5]) array([ 0. , -0.54930614]) - """) + """, +) -add_newdoc('numpy._core.umath', 'bitwise_and', +add_newdoc( + "numpy._core.umath", + "bitwise_and", """ Compute the bit-wise AND of two arrays element-wise. @@ -674,9 +713,12 @@ def add_newdoc(place, name, doc): >>> x1 & x2 array([ 2, 4, 16]) - """) + """, +) -add_newdoc('numpy._core.umath', 'bitwise_or', +add_newdoc( + "numpy._core.umath", + "bitwise_or", """ Compute the bit-wise OR of two arrays element-wise. @@ -743,9 +785,12 @@ def add_newdoc(place, name, doc): >>> x1 | x2 array([ 6, 5, 255]) - """) + """, +) -add_newdoc('numpy._core.umath', 'bitwise_xor', +add_newdoc( + "numpy._core.umath", + "bitwise_xor", """ Compute the bit-wise XOR of two arrays element-wise. @@ -805,9 +850,12 @@ def add_newdoc(place, name, doc): >>> x1 ^ x2 array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'ceil', +add_newdoc( + "numpy._core.umath", + "ceil", """ Return the ceiling of the input, element-wise. @@ -838,9 +886,12 @@ def add_newdoc(place, name, doc): >>> np.ceil(a) array([-1., -1., -0., 1., 2., 2., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'trunc', +add_newdoc( + "numpy._core.umath", + "trunc", """ Return the truncated value of the input, element-wise. @@ -871,9 +922,12 @@ def add_newdoc(place, name, doc): >>> np.trunc(a) array([-1., -1., -0., 0., 1., 1., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'conjugate', +add_newdoc( + "numpy._core.umath", + "conjugate", """ Return the complex conjugate, element-wise. @@ -910,9 +964,12 @@ def add_newdoc(place, name, doc): array([[ 1.-1.j, 0.-0.j], [ 0.-0.j, 1.-1.j]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'cos', +add_newdoc( + "numpy._core.umath", + "cos", """ Cosine element-wise. @@ -956,9 +1013,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'cosh', +add_newdoc( + "numpy._core.umath", + "cosh", """ Hyperbolic cosine, element-wise. @@ -989,9 +1049,12 @@ def add_newdoc(place, name, doc): >>> plt.plot(x, np.cosh(x)) >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'degrees', +add_newdoc( + "numpy._core.umath", + "degrees", """ Convert angles from radians to degrees. @@ -1027,9 +1090,12 @@ def add_newdoc(place, name, doc): >>> np.all(r == out) True - """) + """, +) -add_newdoc('numpy._core.umath', 'rad2deg', +add_newdoc( + "numpy._core.umath", + "rad2deg", """ Convert angles from radians to degrees. @@ -1060,9 +1126,12 @@ def add_newdoc(place, name, doc): >>> np.rad2deg(np.pi/2) 90.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'heaviside', +add_newdoc( + "numpy._core.umath", + "heaviside", """ Compute the Heaviside step function. @@ -1101,9 +1170,12 @@ def add_newdoc(place, name, doc): array([ 0. , 0.5, 1. ]) >>> np.heaviside([-1.5, 0, 2.0], 1) array([ 0., 1., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'divide', +add_newdoc( + "numpy._core.umath", + "divide", """ Divide arguments element-wise. @@ -1156,9 +1228,12 @@ def add_newdoc(place, name, doc): [1.5, 2. , 2.5], [3. , 3.5, 4. ]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'equal', +add_newdoc( + "numpy._core.umath", + "equal", """ Return (x1 == x2) element-wise. @@ -1200,9 +1275,12 @@ def add_newdoc(place, name, doc): >>> a == b array([ True, True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'exp', +add_newdoc( + "numpy._core.umath", + "exp", """ Calculate the exponential of all elements in the input array. @@ -1268,9 +1346,12 @@ def add_newdoc(place, name, doc): >>> plt.title('Phase (angle) of exp(x)') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'exp2', +add_newdoc( + "numpy._core.umath", + "exp2", """ Calculate `2**p` for all `p` in the input array. @@ -1296,9 +1377,12 @@ def add_newdoc(place, name, doc): >>> np.exp2([2, 3]) array([ 4., 8.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'expm1', +add_newdoc( + "numpy._core.umath", + "expm1", """ Calculate ``exp(x) - 1`` for all elements in the array. @@ -1337,9 +1421,12 @@ def add_newdoc(place, name, doc): >>> np.exp(1e-10) - 1 1.000000082740371e-10 - """) + """, +) -add_newdoc('numpy._core.umath', 'fabs', +add_newdoc( + "numpy._core.umath", + "fabs", """ Compute the absolute values element-wise. @@ -1372,9 +1459,12 @@ def add_newdoc(place, name, doc): >>> np.fabs([-1.2, 1.2]) array([ 1.2, 1.2]) - """) + """, +) -add_newdoc('numpy._core.umath', 'floor', +add_newdoc( + "numpy._core.umath", + "floor", """ Return the floor of the input, element-wise. @@ -1411,9 +1501,12 @@ def add_newdoc(place, name, doc): >>> np.floor(a) array([-2., -2., -1., 0., 1., 1., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'floor_divide', +add_newdoc( + "numpy._core.umath", + "floor_divide", """ Return the largest integer smaller or equal to the division of the inputs. It is equivalent to the Python ``//`` operator and pairs with the @@ -1458,9 +1551,12 @@ def add_newdoc(place, name, doc): >>> x1 // 2.5 array([0., 0., 1., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'fmod', +add_newdoc( + "numpy._core.umath", + "fmod", """ Returns the element-wise remainder of division. @@ -1517,9 +1613,12 @@ def add_newdoc(place, name, doc): [-1, 0], [ 1, 0]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'greater', +add_newdoc( + "numpy._core.umath", + "greater", """ Return the truth value of (x1 > x2) element-wise. @@ -1556,9 +1655,12 @@ def add_newdoc(place, name, doc): >>> a > b array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'greater_equal', +add_newdoc( + "numpy._core.umath", + "greater_equal", """ Return the truth value of (x1 >= x2) element-wise. @@ -1594,9 +1696,12 @@ def add_newdoc(place, name, doc): >>> a >= b array([ True, True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'hypot', +add_newdoc( + "numpy._core.umath", + "hypot", """ Given the "legs" of a right triangle, return its hypotenuse. @@ -1633,9 +1738,12 @@ def add_newdoc(place, name, doc): [ 5., 5., 5.], [ 5., 5., 5.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'invert', +add_newdoc( + "numpy._core.umath", + "invert", """ Compute bit-wise inversion, or bit-wise NOT, element-wise. @@ -1723,9 +1831,12 @@ def add_newdoc(place, name, doc): >>> ~x1 array([False, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isfinite', +add_newdoc( + "numpy._core.umath", + "isfinite", """ Test element-wise for finiteness (not infinity and not Not a Number). @@ -1783,9 +1894,12 @@ def add_newdoc(place, name, doc): >>> y array([0, 1, 0]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isinf', +add_newdoc( + "numpy._core.umath", + "isinf", """ Test element-wise for positive or negative infinity. @@ -1836,9 +1950,12 @@ def add_newdoc(place, name, doc): >>> y array([1, 0, 1]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isnan', +add_newdoc( + "numpy._core.umath", + "isnan", """ Test element-wise for NaN and return result as a boolean array. @@ -1873,9 +1990,12 @@ def add_newdoc(place, name, doc): >>> np.isnan([np.log(-1.),1.,np.log(0)]) array([ True, False, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isnat', +add_newdoc( + "numpy._core.umath", + "isnat", """ Test element-wise for NaT (not a time) and return result as a boolean array. @@ -1905,9 +2025,12 @@ def add_newdoc(place, name, doc): >>> np.isnat(np.array(["NaT", "2016-01-01"], dtype="datetime64[ns]")) array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'left_shift', +add_newdoc( + "numpy._core.umath", + "left_shift", """ Shift the bits of an integer to the left. @@ -1968,9 +2091,12 @@ def add_newdoc(place, name, doc): >>> x1 << x2 array([10, 20, 40]) - """) + """, +) -add_newdoc('numpy._core.umath', 'less', +add_newdoc( + "numpy._core.umath", + "less", """ Return the truth value of (x1 < x2) element-wise. @@ -2005,9 +2131,12 @@ def add_newdoc(place, name, doc): >>> a < b array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'less_equal', +add_newdoc( + "numpy._core.umath", + "less_equal", """ Return the truth value of (x1 <= x2) element-wise. @@ -2043,9 +2172,12 @@ def add_newdoc(place, name, doc): >>> a <= b array([False, True, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'log', +add_newdoc( + "numpy._core.umath", + "log", """ Natural logarithm, element-wise. @@ -2101,9 +2233,12 @@ def add_newdoc(place, name, doc): >>> np.log([1, np.e, np.e**2, 0]) array([ 0., 1., 2., -inf]) - """) + """, +) -add_newdoc('numpy._core.umath', 'log10', +add_newdoc( + "numpy._core.umath", + "log10", """ Return the base 10 logarithm of the input array, element-wise. @@ -2156,9 +2291,12 @@ def add_newdoc(place, name, doc): >>> np.log10([1e-15, -3.]) array([-15., nan]) - """) + """, +) -add_newdoc('numpy._core.umath', 'log2', +add_newdoc( + "numpy._core.umath", + "log2", """ Base-2 logarithm of `x`. @@ -2208,9 +2346,12 @@ def add_newdoc(place, name, doc): >>> np.log2(xi) array([ 0.+2.26618007j, 0.+0.j , 1.+0.j , 2.+2.26618007j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logaddexp', +add_newdoc( + "numpy._core.umath", + "logaddexp", """ Logarithm of the sum of exponentiations of the inputs. @@ -2248,9 +2389,12 @@ def add_newdoc(place, name, doc): >>> np.exp(prob12) 3.5000000000000057e-50 - """) + """, +) -add_newdoc('numpy._core.umath', 'logaddexp2', +add_newdoc( + "numpy._core.umath", + "logaddexp2", """ Logarithm of the sum of exponentiations of the inputs in base-2. @@ -2288,9 +2432,12 @@ def add_newdoc(place, name, doc): >>> 2**prob12 3.4999999999999914e-50 - """) + """, +) -add_newdoc('numpy._core.umath', 'log1p', +add_newdoc( + "numpy._core.umath", + "log1p", """ Return the natural logarithm of one plus the input array, element-wise. @@ -2345,9 +2492,12 @@ def add_newdoc(place, name, doc): >>> np.log(1 + 1e-99) 0.0 - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_and', +add_newdoc( + "numpy._core.umath", + "logical_and", """ Compute the truth value of x1 AND x2 element-wise. @@ -2391,9 +2541,12 @@ def add_newdoc(place, name, doc): >>> a & b array([False, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_not', +add_newdoc( + "numpy._core.umath", + "logical_not", """ Compute the truth value of NOT x element-wise. @@ -2426,9 +2579,12 @@ def add_newdoc(place, name, doc): >>> np.logical_not(x<3) array([False, False, False, True, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_or', +add_newdoc( + "numpy._core.umath", + "logical_or", """ Compute the truth value of x1 OR x2 element-wise. @@ -2471,9 +2627,12 @@ def add_newdoc(place, name, doc): >>> a | b array([ True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'logical_xor', +add_newdoc( + "numpy._core.umath", + "logical_xor", """ Compute the truth value of x1 XOR x2, element-wise. @@ -2513,9 +2672,12 @@ def add_newdoc(place, name, doc): array([[ True, False], [False, True]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'maximum', +add_newdoc( + "numpy._core.umath", + "maximum", """ Element-wise maximum of array elements. @@ -2573,9 +2735,12 @@ def add_newdoc(place, name, doc): >>> np.maximum(np.inf, 1) inf - """) + """, +) -add_newdoc('numpy._core.umath', 'minimum', +add_newdoc( + "numpy._core.umath", + "minimum", """ Element-wise minimum of array elements. @@ -2633,9 +2798,12 @@ def add_newdoc(place, name, doc): >>> np.minimum(-np.inf, 1) -inf - """) + """, +) -add_newdoc('numpy._core.umath', 'fmax', +add_newdoc( + "numpy._core.umath", + "fmax", """ Element-wise maximum of array elements. @@ -2690,9 +2858,12 @@ def add_newdoc(place, name, doc): >>> np.fmax([np.nan, 0, np.nan],[0, np.nan, np.nan]) array([ 0., 0., nan]) - """) + """, +) -add_newdoc('numpy._core.umath', 'fmin', +add_newdoc( + "numpy._core.umath", + "fmin", """ Element-wise minimum of array elements. @@ -2747,9 +2918,12 @@ def add_newdoc(place, name, doc): >>> np.fmin([np.nan, 0, np.nan],[0, np.nan, np.nan]) array([ 0., 0., nan]) - """) + """, +) -add_newdoc('numpy._core.umath', 'clip', +add_newdoc( + "numpy._core.umath", + "clip", """ Clip (limit) the values in an array. @@ -2787,9 +2961,12 @@ def add_newdoc(place, name, doc): An array with the elements of `a`, but where values < `a_min` are replaced with `a_min`, and those > `a_max` with `a_max`. - """) + """, +) -add_newdoc('numpy._core.umath', 'matmul', +add_newdoc( + "numpy._core.umath", + "matmul", """ Matrix product of two arrays. @@ -2917,9 +3094,12 @@ def add_newdoc(place, name, doc): >>> x2 = np.array([2j, 3j]) >>> x1 @ x2 (-13+0j) - """) + """, +) -add_newdoc('numpy._core.umath', 'vecdot', +add_newdoc( + "numpy._core.umath", + "vecdot", """ Vector dot product of two arrays. @@ -2980,9 +3160,12 @@ def add_newdoc(place, name, doc): >>> np.vecdot(v, n) array([ 3., 8., 10.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'matvec', +add_newdoc( + "numpy._core.umath", + "matvec", """ Matrix-vector dot product of two arrays. @@ -3047,9 +3230,12 @@ def add_newdoc(place, name, doc): [ 0., 0., 1.], [ 6., 0., 8.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'vecmat', +add_newdoc( + "numpy._core.umath", + "vecmat", """ Vector-matrix dot product of two arrays. @@ -3111,9 +3297,12 @@ def add_newdoc(place, name, doc): >>> np.vecmat(v, a) array([ 0., 4., 0.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'modf', +add_newdoc( + "numpy._core.umath", + "modf", """ Return the fractional and integral parts of an array, element-wise. @@ -3152,9 +3341,12 @@ def add_newdoc(place, name, doc): >>> np.modf(-0.5) (-0.5, -0) - """) + """, +) -add_newdoc('numpy._core.umath', 'multiply', +add_newdoc( + "numpy._core.umath", + "multiply", """ Multiply arguments element-wise. @@ -3198,9 +3390,12 @@ def add_newdoc(place, name, doc): [ 0., 4., 10.], [ 0., 7., 16.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'negative', +add_newdoc( + "numpy._core.umath", + "negative", """ Numerical negative, element-wise. @@ -3229,9 +3424,12 @@ def add_newdoc(place, name, doc): >>> -x1 array([-1., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'positive', +add_newdoc( + "numpy._core.umath", + "positive", """ Numerical positive, element-wise. @@ -3266,9 +3464,12 @@ def add_newdoc(place, name, doc): >>> +x1 array([ 1., -1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'not_equal', +add_newdoc( + "numpy._core.umath", + "not_equal", """ Return (x1 != x2) element-wise. @@ -3308,9 +3509,12 @@ def add_newdoc(place, name, doc): array([False, True]) - """) + """, +) -add_newdoc('numpy._core.umath', '_ones_like', +add_newdoc( + "numpy._core.umath", + "_ones_like", """ This function used to be the numpy.ones_like, but now a specific function for that has been written for consistency with the other @@ -3320,9 +3524,12 @@ def add_newdoc(place, name, doc): -------- ones_like - """) + """, +) -add_newdoc('numpy._core.umath', 'power', +add_newdoc( + "numpy._core.umath", + "power", """ First array elements raised to powers from second array, element-wise. @@ -3406,9 +3613,12 @@ def add_newdoc(place, name, doc): >>> np.power(x3, 1.5, dtype=complex) array([-1.83697020e-16-1.j, -1.46957616e-15-8.j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'float_power', +add_newdoc( + "numpy._core.umath", + "float_power", """ First array elements raised to powers from second array, element-wise. @@ -3485,9 +3695,12 @@ def add_newdoc(place, name, doc): >>> np.float_power(x3, 1.5, dtype=complex) array([-1.83697020e-16-1.j, -1.46957616e-15-8.j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'radians', +add_newdoc( + "numpy._core.umath", + "radians", """ Convert angles from degrees to radians. @@ -3524,9 +3737,12 @@ def add_newdoc(place, name, doc): >>> ret is out True - """) + """, +) -add_newdoc('numpy._core.umath', 'deg2rad', +add_newdoc( + "numpy._core.umath", + "deg2rad", """ Convert angles from degrees to radians. @@ -3557,9 +3773,12 @@ def add_newdoc(place, name, doc): >>> np.deg2rad(180) 3.1415926535897931 - """) + """, +) -add_newdoc('numpy._core.umath', 'reciprocal', +add_newdoc( + "numpy._core.umath", + "reciprocal", """ Return the reciprocal of the argument, element-wise. @@ -3594,9 +3813,12 @@ def add_newdoc(place, name, doc): >>> np.reciprocal([1, 2., 3.33]) array([ 1. , 0.5 , 0.3003003]) - """) + """, +) -add_newdoc('numpy._core.umath', 'remainder', +add_newdoc( + "numpy._core.umath", + "remainder", """ Returns the element-wise remainder of division. @@ -3658,9 +3880,12 @@ def add_newdoc(place, name, doc): >>> x1 % 5 array([0, 1, 2, 3, 4, 0, 1]) - """) + """, +) -add_newdoc('numpy._core.umath', 'divmod', +add_newdoc( + "numpy._core.umath", + "divmod", """ Return element-wise quotient and remainder simultaneously. @@ -3706,9 +3931,12 @@ def add_newdoc(place, name, doc): >>> divmod(x, 3) (array([0, 0, 0, 1, 1]), array([0, 1, 2, 0, 1])) - """) + """, +) -add_newdoc('numpy._core.umath', 'right_shift', +add_newdoc( + "numpy._core.umath", + "right_shift", """ Shift the bits of an integer to the right. @@ -3758,9 +3986,12 @@ def add_newdoc(place, name, doc): >>> x1 >> x2 array([5, 2, 1]) - """) + """, +) -add_newdoc('numpy._core.umath', 'rint', +add_newdoc( + "numpy._core.umath", + "rint", """ Round elements of the array to the nearest integer. @@ -3793,9 +4024,12 @@ def add_newdoc(place, name, doc): >>> np.rint(a) array([-2., -2., -0., 0., 2., 2., 2.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'sign', +add_newdoc( + "numpy._core.umath", + "sign", """ Returns an element-wise indication of the sign of a number. @@ -3838,9 +4072,12 @@ def add_newdoc(place, name, doc): >>> np.sign([3-4j, 8j]) array([0.6-0.8j, 0. +1.j ]) - """) + """, +) -add_newdoc('numpy._core.umath', 'signbit', +add_newdoc( + "numpy._core.umath", + "signbit", """ Returns element-wise True where signbit is set (less than zero). @@ -3864,9 +4101,12 @@ def add_newdoc(place, name, doc): >>> np.signbit(np.array([1, -2.3, 2.1])) array([False, True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'copysign', +add_newdoc( + "numpy._core.umath", + "copysign", """ Change the sign of x1 to that of x2, element-wise. @@ -3902,9 +4142,12 @@ def add_newdoc(place, name, doc): >>> np.copysign([-1, 0, 1], np.arange(3)-1) array([-1., 0., 1.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'nextafter', +add_newdoc( + "numpy._core.umath", + "nextafter", """ Return the next floating-point value after x1 towards x2, element-wise. @@ -3932,9 +4175,12 @@ def add_newdoc(place, name, doc): >>> np.nextafter([1, 2], [2, 1]) == [eps + 1, 2 - eps] array([ True, True]) - """) + """, +) -add_newdoc('numpy._core.umath', 'spacing', +add_newdoc( + "numpy._core.umath", + "spacing", """ Return the distance between x and the nearest adjacent number. @@ -3965,9 +4211,12 @@ def add_newdoc(place, name, doc): >>> np.spacing(1) == np.finfo(np.float64).eps True - """) + """, +) -add_newdoc('numpy._core.umath', 'sin', +add_newdoc( + "numpy._core.umath", + "sin", """ Trigonometric sine, element-wise. @@ -4025,9 +4274,12 @@ def add_newdoc(place, name, doc): >>> plt.axis('tight') >>> plt.show() - """) + """, +) -add_newdoc('numpy._core.umath', 'sinh', +add_newdoc( + "numpy._core.umath", + "sinh", """ Hyperbolic sine, element-wise. @@ -4079,9 +4331,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'sqrt', +add_newdoc( + "numpy._core.umath", + "sqrt", """ Return the non-negative square-root of an array, element-wise. @@ -4127,9 +4382,12 @@ def add_newdoc(place, name, doc): >>> np.sqrt([4, -1, np.inf]) array([ 2., nan, inf]) - """) + """, +) -add_newdoc('numpy._core.umath', 'cbrt', +add_newdoc( + "numpy._core.umath", + "cbrt", """ Return the cube-root of an array, element-wise. @@ -4154,9 +4412,12 @@ def add_newdoc(place, name, doc): >>> np.cbrt([1,8,27]) array([ 1., 2., 3.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'square', +add_newdoc( + "numpy._core.umath", + "square", """ Return the element-wise square of the input. @@ -4184,9 +4445,12 @@ def add_newdoc(place, name, doc): >>> np.square([-1j, 1]) array([-1.-0.j, 1.+0.j]) - """) + """, +) -add_newdoc('numpy._core.umath', 'subtract', +add_newdoc( + "numpy._core.umath", + "subtract", """ Subtract arguments, element-wise. @@ -4230,9 +4494,12 @@ def add_newdoc(place, name, doc): [3., 3., 3.], [6., 6., 6.]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'tan', +add_newdoc( + "numpy._core.umath", + "tan", """ Compute tangent element-wise. @@ -4280,9 +4547,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'tanh', +add_newdoc( + "numpy._core.umath", + "tanh", """ Compute hyperbolic tangent element-wise. @@ -4333,9 +4603,12 @@ def add_newdoc(place, name, doc): File "", line 1, in ValueError: operands could not be broadcast together with shapes (3,3) (2,2) - """) + """, +) -add_newdoc('numpy._core.umath', 'frexp', +add_newdoc( + "numpy._core.umath", + "frexp", """ Decompose the elements of x into mantissa and twos exponent. @@ -4383,9 +4656,12 @@ def add_newdoc(place, name, doc): >>> y1 * 2**y2 array([ 0., 1., 2., 3., 4., 5., 6., 7., 8.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'ldexp', +add_newdoc( + "numpy._core.umath", + "ldexp", """ Returns x1 * 2**x2, element-wise. @@ -4428,9 +4704,12 @@ def add_newdoc(place, name, doc): >>> np.ldexp(*np.frexp(x)) array([ 0., 1., 2., 3., 4., 5.]) - """) + """, +) -add_newdoc('numpy._core.umath', 'gcd', +add_newdoc( + "numpy._core.umath", + "gcd", """ Returns the greatest common divisor of ``|x1|`` and ``|x2|`` @@ -4460,9 +4739,12 @@ def add_newdoc(place, name, doc): >>> np.gcd(np.arange(6), 20) array([20, 1, 2, 1, 4, 5]) - """) + """, +) -add_newdoc('numpy._core.umath', 'lcm', +add_newdoc( + "numpy._core.umath", + "lcm", """ Returns the lowest common multiple of ``|x1|`` and ``|x2|`` @@ -4494,9 +4776,12 @@ def add_newdoc(place, name, doc): >>> np.lcm(np.arange(6), 20) array([ 0, 20, 20, 60, 20, 20]) - """) + """, +) -add_newdoc('numpy._core.umath', 'bitwise_count', +add_newdoc( + "numpy._core.umath", + "bitwise_count", """ Computes the number of 1-bits in the absolute value of ``x``. Analogous to the builtin `int.bit_count` or ``popcount`` in C++. @@ -4533,9 +4818,12 @@ def add_newdoc(place, name, doc): array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], dtype=uint8) - """) + """, +) -add_newdoc('numpy._core.umath', 'str_len', +add_newdoc( + "numpy._core.umath", + "str_len", """ Returns the length of each element. For byte strings, this is the number of bytes, while, for Unicode strings, @@ -4569,9 +4857,12 @@ def add_newdoc(place, name, doc): >>> np.strings.str_len(a) array([[5, 5], [1, 1]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isalpha', +add_newdoc( + "numpy._core.umath", + "isalpha", """ Returns true for each element if all characters in the data interpreted as a string are alphabetic and there is at least @@ -4609,9 +4900,12 @@ def add_newdoc(place, name, doc): >>> np.strings.isalpha(a) array([[ True, True, False], [ True, False, False]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isdigit', +add_newdoc( + "numpy._core.umath", + "isdigit", """ Returns true for each element if all characters in the string are digits and there is at least one character, false otherwise. @@ -4647,9 +4941,12 @@ def add_newdoc(place, name, doc): >>> np.strings.isdigit(a) array([[False, False, True], [False, True, True]]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isspace', +add_newdoc( + "numpy._core.umath", + "isspace", r""" Returns true for each element if there are only whitespace characters in the string and there is at least one character, @@ -4685,9 +4982,12 @@ def add_newdoc(place, name, doc): >>> np.char.isspace(b'\x0a \x0b \x0c N') np.False_ - """) + """, +) -add_newdoc('numpy._core.umath', 'isalnum', +add_newdoc( + "numpy._core.umath", + "isalnum", """ Returns true for each element if all characters in the string are alphanumeric and there is at least one character, false otherwise. @@ -4714,9 +5014,12 @@ def add_newdoc(place, name, doc): >>> np.strings.isalnum(a) array([ True, True, True, False, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'islower', +add_newdoc( + "numpy._core.umath", + "islower", """ Returns true for each element if all cased characters in the string are lowercase and there is at least one cased character, @@ -4745,9 +5048,12 @@ def add_newdoc(place, name, doc): >>> np.strings.islower("ghc") array(True) - """) + """, +) -add_newdoc('numpy._core.umath', 'isupper', +add_newdoc( + "numpy._core.umath", + "isupper", """ Return true for each element if all cased characters in the string are uppercase and there is at least one character, false @@ -4777,9 +5083,12 @@ def add_newdoc(place, name, doc): >>> np.strings.isupper(a) array([False, True, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'istitle', +add_newdoc( + "numpy._core.umath", + "istitle", """ Returns true for each element if the element is a titlecased string and there is at least one character, false otherwise. @@ -4808,9 +5117,12 @@ def add_newdoc(place, name, doc): >>> np.strings.istitle("Numpy is great") array(False) - """) + """, +) -add_newdoc('numpy._core.umath', 'isdecimal', +add_newdoc( + "numpy._core.umath", + "isdecimal", """ For each element, return True if there are only decimal characters in the element. @@ -4840,9 +5152,12 @@ def add_newdoc(place, name, doc): >>> np.strings.isdecimal(['12345', '4.99', '123ABC', '']) array([ True, False, False, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'isnumeric', +add_newdoc( + "numpy._core.umath", + "isnumeric", """ For each element, return True if there are only numeric characters in the element. @@ -4872,9 +5187,12 @@ def add_newdoc(place, name, doc): >>> np.strings.isnumeric(['123', '123abc', '9.0', '1/4', 'VIII']) array([ True, False, False, False, False]) - """) + """, +) -add_newdoc('numpy._core.umath', 'find', +add_newdoc( + "numpy._core.umath", + "find", """ For each element, return the lowest index in the string where substring `x2` is found, such that `x2` is contained in the @@ -4910,9 +5228,12 @@ def add_newdoc(place, name, doc): >>> np.strings.find(a, "Python", 0, None) array([11]) - """) + """, +) -add_newdoc('numpy._core.umath', 'rfind', +add_newdoc( + "numpy._core.umath", + "rfind", """ For each element, return the highest index in the string where substring `x2` is found, such that `x2` is contained in the @@ -4941,9 +5262,12 @@ def add_newdoc(place, name, doc): -------- str.rfind - """) + """, +) -add_newdoc('numpy._core.umath', 'count', +add_newdoc( + "numpy._core.umath", + "count", """ Returns an array with the number of non-overlapping occurrences of substring `x2` in the range [`x3`, `x4`]. @@ -4987,9 +5311,12 @@ def add_newdoc(place, name, doc): >>> np.strings.count(c, 'A', start=1, end=3) array([1, 0, 0]) - """) + """, +) -add_newdoc('numpy._core.umath', 'index', +add_newdoc( + "numpy._core.umath", + "index", """ Like `find`, but raises :exc:`ValueError` when the substring is not found. @@ -5020,9 +5347,12 @@ def add_newdoc(place, name, doc): >>> np.strings.index(a, "Science") array([9]) - """) + """, +) -add_newdoc('numpy._core.umath', 'rindex', +add_newdoc( + "numpy._core.umath", + "rindex", """ Like `rfind`, but raises :exc:`ValueError` when the substring is not found. @@ -5053,16 +5383,22 @@ def add_newdoc(place, name, doc): >>> np.strings.rindex(a, "Science") array([9]) - """) + """, +) -add_newdoc('numpy._core.umath', '_replace', +add_newdoc( + "numpy._core.umath", + "_replace", """ UFunc implementation of ``replace``. This internal function is called by ``replace`` with ``out`` set, so that the size of the resulting string buffer is known. - """) + """, +) -add_newdoc('numpy._core.umath', 'startswith', +add_newdoc( + "numpy._core.umath", + "startswith", """ Returns a boolean array which is `True` where the string element in `x1` starts with `x2`, otherwise `False`. @@ -5090,9 +5426,12 @@ def add_newdoc(place, name, doc): -------- str.startswith - """) + """, +) -add_newdoc('numpy._core.umath', 'endswith', +add_newdoc( + "numpy._core.umath", + "endswith", """ Returns a boolean array which is `True` where the string element in `x1` ends with `x2`, otherwise `False`. @@ -5131,19 +5470,22 @@ def add_newdoc(place, name, doc): >>> np.strings.endswith(s, 'a', start=1, end=2) array([False, True]) - """) + """, +) -add_newdoc('numpy._core.umath', '_strip_chars', '') -add_newdoc('numpy._core.umath', '_lstrip_chars', '') -add_newdoc('numpy._core.umath', '_rstrip_chars', '') -add_newdoc('numpy._core.umath', '_strip_whitespace', '') -add_newdoc('numpy._core.umath', '_lstrip_whitespace', '') -add_newdoc('numpy._core.umath', '_rstrip_whitespace', '') +add_newdoc("numpy._core.umath", "_strip_chars", "") +add_newdoc("numpy._core.umath", "_lstrip_chars", "") +add_newdoc("numpy._core.umath", "_rstrip_chars", "") +add_newdoc("numpy._core.umath", "_strip_whitespace", "") +add_newdoc("numpy._core.umath", "_lstrip_whitespace", "") +add_newdoc("numpy._core.umath", "_rstrip_whitespace", "") -add_newdoc('numpy._core.umath', '_expandtabs_length', '') -add_newdoc('numpy._core.umath', '_expandtabs', '') +add_newdoc("numpy._core.umath", "_expandtabs_length", "") +add_newdoc("numpy._core.umath", "_expandtabs", "") -add_newdoc('numpy._core.umath', '_center', +add_newdoc( + "numpy._core.umath", + "_center", """ Return a copy of `x1` with its elements centered in a string of length `x2`. @@ -5181,9 +5523,12 @@ def add_newdoc(place, name, doc): >>> np.strings.center(c, width=1) array(['a1b2', '1b2a', 'b2a1', '2a1b'], dtype='>> np.strings.ljust(c, width=9) array(['aAaAaA ', ' aA ', 'abBABba '], dtype='>> np.strings.rjust(a, width=9) array([' aAaAaA', ' aA ', ' abBABba'], dtype='>> np.strings.zfill(['1', '-1', '+1'], 3) array(['001', '-01', '+01'], dtype='>> np.strings.slice(a, 2) array(['he', 'wo'], dtype='=77", - "Cython", - "numpy" + "cmake", + "ninja", + "scikit-build", + "setuptools>=77", + "Cython", + "numpy" ] [project] authors = [ - {name = "Intel Corporation", email = "scripting@intel.com"} + {name = "Intel Corporation", email = "scripting@intel.com"} ] classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Science/Research", - "Intended Audience :: Developers", - "Programming Language :: C", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", - "Programming Language :: Python :: Implementation :: CPython", - "Topic :: Software Development", - "Topic :: Scientific/Engineering", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX", - "Operating System :: Unix" + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "Programming Language :: C", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Software Development", + "Topic :: Scientific/Engineering", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Operating System :: Unix" ] dependencies = ["numpy >=1.26.4", "mkl-service"] description = "Intel (R) MKL-based universal functions for NumPy arrays" @@ -66,7 +66,6 @@ name = "mkl_umath" readme = {file = "README.md", content-type = "text/markdown"} requires-python = ">=3.10,<3.15" - [project.optional-dependencies] test = ["pytest"] @@ -74,5 +73,26 @@ test = ["pytest"] Download = "http://github.com/IntelPython/mkl_umath" Homepage = "http://github.com/IntelPython/mkl_umath" +[tool.black] +exclude = "_vendored/conv_template.py" +line-length = 80 + +[tool.cython-lint] +ignore = ['E722'] # do not use bare 'except' +max-line-length = 80 + +[tool.isort] +ensure_newline_before_comments = true +force_grid_wrap = 0 +include_trailing_comma = true +line_length = 80 +multi_line_output = 3 +skip = ["_vendored/conv_template.py"] +use_parentheses = true + +[tool.setuptools] +include-package-data = true +packages = ["mkl_umath"] + [tool.setuptools.dynamic] version = {attr = "mkl_umath._version.__version__"} diff --git a/setup.py b/setup.py index f13b348..2eef2e1 100644 --- a/setup.py +++ b/setup.py @@ -25,23 +25,22 @@ import importlib.machinery import sys -from setuptools.modified import newer from os import makedirs -from os.path import join, exists, dirname +from os.path import dirname, exists, join import skbuild +from setuptools.modified import newer sys.path.insert(0, dirname(__file__)) # Ensures local imports work -from _vendored.conv_template import process_file as process_c_file +from _vendored.conv_template import process_file as process_c_file # noqa: E402 # TODO: rewrite generation in CMake, see NumPy meson implementation # https://github.com/numpy/numpy/blob/c6fb3357541fd8cf6e4faeaeda3b1a9065da0520/numpy/_core/meson.build#L623 def load_module(name, fn): - """ - Credit: numpy.compat.npy_load_module - """ - return importlib.machinery.SourceFileLoader(name, fn).load_module() + """Credit: numpy.compat.npy_load_module""" + return importlib.machinery.SourceFileLoader(name, fn).load_module(name) + def separator_join(sep, strs): """ @@ -53,26 +52,32 @@ def separator_join(sep, strs): assert isinstance(sep, str) return sep.join([si for si in strs if si]) -pdir = join(dirname(__file__), 'mkl_umath') -wdir = join(pdir, 'src') -generate_umath_py = join(pdir, 'generate_umath.py') -n = separator_join('_', ('mkl_umath', 'generate_umath')) +pdir = join(dirname(__file__), "mkl_umath") +wdir = join(pdir, "src") + +generate_umath_py = join(pdir, "generate_umath.py") +n = separator_join("_", ("mkl_umath", "generate_umath")) generate_umath = load_module(n, generate_umath_py) del n def generate_umath_c(build_dir): - target_dir = join(build_dir, 'src') - target = join(target_dir, '__umath_generated.c') + target_dir = join(build_dir, "src") + target = join(target_dir, "__umath_generated.c") if not exists(target_dir): - print("Folder {} was expected to exist, but creating".format(target_dir)) + print( + "Folder {} was expected to exist, but creating".format(target_dir) + ) makedirs(target_dir) script = generate_umath_py if newer(script, target): - with open(target, 'w') as f: - f.write(generate_umath.make_code(generate_umath.defdict, - generate_umath.__file__)) + with open(target, "w") as f: + f.write( + generate_umath.make_code( + generate_umath.defdict, generate_umath.__file__ + ) + ) return [] @@ -82,14 +87,14 @@ def generate_umath_c(build_dir): processed_loops_h_fn = join(wdir, "mkl_umath_loops.h") loops_header_processed = process_c_file(loops_header_templ) -with open(processed_loops_h_fn, 'w') as fid: +with open(processed_loops_h_fn, "w") as fid: fid.write(loops_header_processed) loops_src_templ = join(wdir, "mkl_umath_loops.c.src") processed_loops_src_fn = join(wdir, "mkl_umath_loops.c") loops_src_processed = process_c_file(loops_src_templ) -with open(processed_loops_src_fn, 'w') as fid: +with open(processed_loops_src_fn, "w") as fid: fid.write(loops_src_processed) From c2b2921321f905161f9de70944d03815da5b909c Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Fri, 27 Feb 2026 00:43:21 -0800 Subject: [PATCH 2/4] add pre-commit workflow and auto-update workflow --- .github/workflows/pre-commit-autoupdate.yml | 49 +++++++++++++++++++++ .github/workflows/pre-commit.yml | 31 +++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 .github/workflows/pre-commit-autoupdate.yml create mode 100644 .github/workflows/pre-commit.yml diff --git a/.github/workflows/pre-commit-autoupdate.yml b/.github/workflows/pre-commit-autoupdate.yml new file mode 100644 index 0000000..e7d274e --- /dev/null +++ b/.github/workflows/pre-commit-autoupdate.yml @@ -0,0 +1,49 @@ +name: Autoupdate pre-commit + +on: + workflow_dispatch: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '28 2 * * 6' # Saturday at 02:28 UTC + +permissions: read-all + +jobs: + autoupdate: + name: Autoupdate + + runs-on: ubuntu-latest + timeout-minutes: 10 + + permissions: + # Needed to create a PR with autoupdate changes + contents: write + pull-requests: write + + steps: + - name: Checkout repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v5.6.0 + with: + python-version: '3.14' + + - name: Install pre-commit + run: pip install pre-commit + + - name: Run pre-commit autoupdate + run: pre-commit autoupdate + + - name: Create a PR with autoupdate changes + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + with: + commit-message: 'chore: update pre-commit hooks' + add-paths: .pre-commit-config.yaml + branch: 'bot/pre-commit-autoupdate' + delete-branch: true + title: Weekly pre-commit autoupdate + body: | + This PR updates the `.pre-commit-config.yaml` using `pre-commit autoupdate`. + labels: autoupdate diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..e7b2380 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,31 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [master] + +permissions: read-all + +jobs: + pre-commit: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.14' + + - name: Set up pip packages + uses: BSFishy/pip-action@8f2d471d809dc20b6ada98c91910b6ae6243f318 # v1 + with: + packages: | + codespell + pylint + + - name: Run pre-commit checks + uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 From ebed681561bbbc4e47085a77e2218f04fdce50f6 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Fri, 27 Feb 2026 00:45:34 -0800 Subject: [PATCH 3/4] add .git-blame-ignore-revs and add pre-commit changes to it --- .git-blame-ignore-revs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..222822d --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,4 @@ +# $ git config blame.ignoreRevsFile .git-blame-ignore-revs + +# Added pre-commit hooks +0a6a8df577a72ce9b54fc2450ea6644b0ad770b7 From 52b0dcf5ed9553d1b3c05ce7386a6f54863d2494 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Fri, 27 Feb 2026 01:25:28 -0800 Subject: [PATCH 4/4] use bash arrays in build scripts --- conda-recipe-cf/build.sh | 14 ++++++++++---- conda-recipe/build.sh | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/conda-recipe-cf/build.sh b/conda-recipe-cf/build.sh index 155ca2c..00414a1 100644 --- a/conda-recipe-cf/build.sh +++ b/conda-recipe-cf/build.sh @@ -12,14 +12,20 @@ read -r GLIBC_MAJOR GLIBC_MINOR <<< "$(conda list '^sysroot_linux-64$' \ | tail -n 1 | awk '{print $2}' | grep -oP '\d+' | head -n 2 | tr '\n' ' ')" export CMAKE_GENERATOR="Ninja" -SKBUILD_ARGS="-- -DCMAKE_C_COMPILER:PATH=icx -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" +SKBUILD_ARGS=( + "--" + "-DCMAKE_C_COMPILER:PATH=icx" + "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" +) if [ -n "${WHEELS_OUTPUT_FOLDER}" ]; then # Install packages and assemble wheel package from built bits - WHEELS_BUILD_ARGS="-p manylinux_${GLIBC_MAJOR}_${GLIBC_MINOR}_x86_64" - ${PYTHON} setup.py install bdist_wheel "${WHEELS_BUILD_ARGS}" "${SKBUILD_ARGS}" + WHEELS_BUILD_ARGS=( + "-p" "manylinux_${GLIBC_MAJOR}_${GLIBC_MINOR}_x86_64" + ) + ${PYTHON} setup.py install bdist_wheel "${WHEELS_BUILD_ARGS[@]}" "${SKBUILD_ARGS[@]}" cp dist/mkl_umath*.whl "${WHEELS_OUTPUT_FOLDER}" else # Perform regular install - ${PYTHON} setup.py install "${SKBUILD_ARGS}" + ${PYTHON} setup.py install "${SKBUILD_ARGS[@]}" fi diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh index 155ca2c..00414a1 100644 --- a/conda-recipe/build.sh +++ b/conda-recipe/build.sh @@ -12,14 +12,20 @@ read -r GLIBC_MAJOR GLIBC_MINOR <<< "$(conda list '^sysroot_linux-64$' \ | tail -n 1 | awk '{print $2}' | grep -oP '\d+' | head -n 2 | tr '\n' ' ')" export CMAKE_GENERATOR="Ninja" -SKBUILD_ARGS="-- -DCMAKE_C_COMPILER:PATH=icx -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" +SKBUILD_ARGS=( + "--" + "-DCMAKE_C_COMPILER:PATH=icx" + "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" +) if [ -n "${WHEELS_OUTPUT_FOLDER}" ]; then # Install packages and assemble wheel package from built bits - WHEELS_BUILD_ARGS="-p manylinux_${GLIBC_MAJOR}_${GLIBC_MINOR}_x86_64" - ${PYTHON} setup.py install bdist_wheel "${WHEELS_BUILD_ARGS}" "${SKBUILD_ARGS}" + WHEELS_BUILD_ARGS=( + "-p" "manylinux_${GLIBC_MAJOR}_${GLIBC_MINOR}_x86_64" + ) + ${PYTHON} setup.py install bdist_wheel "${WHEELS_BUILD_ARGS[@]}" "${SKBUILD_ARGS[@]}" cp dist/mkl_umath*.whl "${WHEELS_OUTPUT_FOLDER}" else # Perform regular install - ${PYTHON} setup.py install "${SKBUILD_ARGS}" + ${PYTHON} setup.py install "${SKBUILD_ARGS[@]}" fi