Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
* Raised the minimum NumPy version to 2.0 at build time and at runtime in `pyproject.toml` and the conda recipe. `mkl_umath` built against NumPy 2 kept NumPy 2 behavior when run with NumPy 1.x, which the previous `numpy >=1.26.4` requirement allowed: complex `sign` returned NumPy 2 results and, on Windows, `patch_numpy_umath()` could not find NumPy loops matching the `int64` `ldexp` loops [gh-289](https://github.com/IntelPython/mkl_umath/pull/289)

### Fixed
* Fixed the ufunc docstrings, which held only the name of the C macro meant to supply them (e.g. `DOC_NUMPY__CORE_UMATH_SIN`): the docstring header is now generated by the build and included in the generated ufunc code [gh-282](https://github.com/IntelPython/mkl_umath/pull/282)

### Removed
* Removed the NumPy 1 code paths: the `USE_NUMPY_2` switch with the NumPy 1 complex `sign` and `ldexp_long` loops, and `ufunc_docstrings_numpy1.py`. Building against NumPy 1 headers now fails with an explicit error [gh-289](https://github.com/IntelPython/mkl_umath/pull/289)

Expand Down
13 changes: 12 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ gen_umath_c = custom_target(
command: [py, '@INPUT@', '-o', '@OUTPUT@']
)

gen_umath_doc_h = custom_target(
'_umath_doc_generated',
output: '_umath_doc_generated.h',
input: 'mkl_umath/generate_umath_doc.py',
command: [py, '@INPUT@', '-o', '@OUTPUT@'],
depend_files: ['mkl_umath/ufunc_docstrings_numpy2.py']
)

gen_loops_h = custom_target(
'mkl_umath_loops_h',
output: ['mkl_umath_loops.h'],
Expand Down Expand Up @@ -189,7 +197,10 @@ loops_dep = declare_dependency(link_with: mkl_umath_loops)

py.extension_module(
'_ufuncs',
sources: ['mkl_umath/src/ufuncsmodule.c', gen_umath_c, gen_loops_h],
sources: [
'mkl_umath/src/ufuncsmodule.c', gen_umath_c, gen_umath_doc_h,
gen_loops_h
],
include_directories: inc_np,
dependencies: [mkl_dep, loops_dep],
c_args: c_args + ['-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION'],
Expand Down
6 changes: 3 additions & 3 deletions mkl_umath/generate_umath.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
# 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}_*"`
# 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.
# 3) In the `make_code` function, the string used there is different.

"""
Generate the code to build all the internal ufuncs. At the base is the defdict:
Expand Down Expand Up @@ -1151,7 +1150,7 @@ def make_ufuncs(funcdict):
f = PyUFunc_FromFuncAndDataAndSignatureAndIdentity(
{funcs}, {data}, {signatures}, {nloops},
{nin}, {nout}, {identity}, "{name}",
"{doc}", 0, {sig}, identity
{doc}, 0, {sig}, identity
);
if ({has_identity}) {{
Py_DECREF(identity);
Expand Down Expand Up @@ -1244,6 +1243,7 @@ def make_code(funcdict, filename):
#include "numpy/arrayobject.h"
#include "numpy/ufuncobject.h"
#include "mkl_umath_loops.h"
#include "_umath_doc_generated.h"
%s

static int
Expand Down
8 changes: 8 additions & 0 deletions mkl_umath/tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,11 @@ def test_absolute_nan_signbit(size, dtype):
f"absolute({sign}nan) must be +nan for "
f"{dtype.__name__} at size {size}"
)


@pytest.mark.parametrize("func", umaths)
def test_docstring(func):
# the ufunc must carry the docstring text, not the name of its C macro
doc = getattr(mu, func).__doc__
assert "DOC_" not in doc, f"'{func}' docstring is an unexpanded macro"
assert "Parameters" in doc, f"'{func}' docstring is missing its body"
Loading