Skip to content
Merged
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
112 changes: 112 additions & 0 deletions ad/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,118 @@
def __bool__(self) -> bool:
return bool(self.x)

def __array_ufunc__( # noqa: PLW3201

Check failure on line 785 in ad/__init__.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=eggzec_ad&issues=AZ5BhaI3jwCU4LvpDRk7&open=AZ5BhaI3jwCU4LvpDRk7&pullRequest=24
self, ufunc: object, method: str, *inputs: object, **kwargs: object
) -> object:
"""Support NumPy ufunc dispatch (e.g. ``numpy.sin(x)``) on ADF objects.

Returns
-------
object
Result of the corresponding ``admath`` function, element-wise
result for arithmetic ufuncs, or ``NotImplemented`` if the
ufunc has no mapping.
"""
if method != "__call__":
return NotImplemented

import operator # noqa: PLC0415

import numpy as np # noqa: PLC0415

import ad.admath as adm # noqa: PLC0415

math_ufunc_map = {
np.sin: adm.sin,
np.cos: adm.cos,
np.tan: adm.tan,
np.arcsin: adm.asin,
np.arccos: adm.acos,
np.arctan: adm.atan,
np.arctan2: adm.atan2,
np.sinh: adm.sinh,
np.cosh: adm.cosh,
np.tanh: adm.tanh,
np.arcsinh: adm.asinh,
np.arccosh: adm.acosh,
np.arctanh: adm.atanh,
np.exp: adm.exp,
np.expm1: adm.expm1,
np.log: adm.log,
np.log10: adm.log10,
np.log1p: adm.log1p,
np.sqrt: adm.sqrt,
np.ceil: adm.ceil,
np.floor: adm.floor,
np.trunc: adm.trunc,
np.hypot: adm.hypot,
np.degrees: adm.degrees,
np.radians: adm.radians,
np.power: adm.power,
}

adm_func = math_ufunc_map.get(ufunc) # type: ignore[arg-type]
if adm_func is not None:
result = adm_func(*inputs)
out = kwargs.get("out")
if out is not None:
out[0][...] = result
return result

arith_ufunc_map = {
np.multiply: operator.mul,
np.add: operator.add,
np.subtract: operator.sub,
np.true_divide: operator.truediv,
np.floor_divide: operator.floordiv,
np.remainder: operator.mod,
np.negative: operator.neg,
np.positive: operator.pos,
np.absolute: abs,
np.fabs: abs,
}

arith_op = arith_ufunc_map.get(ufunc) # type: ignore[arg-type]
if arith_op is None:
return NotImplemented

def _to_py(v: object) -> object:
return v.item() if isinstance(v, np.generic) else v # type: ignore[union-attr]

def _apply(op: object, a: object, b: object = None) -> object: # type: ignore[assignment]
if b is None:
if isinstance(a, np.ndarray):
return np.array( # type: ignore[call-overload]
[op(_to_py(xi)) for xi in a.flat], # type: ignore[operator]

Check warning on line 867 in ad/__init__.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Fix this call; Previous type checks suggest that "op" has type object and it is not callable.

See more on https://sonarcloud.io/project/issues?id=eggzec_ad&issues=AZ5BhaI3jwCU4LvpDRk8&open=AZ5BhaI3jwCU4LvpDRk8&pullRequest=24
dtype=object,
).reshape(a.shape)
return op(_to_py(a)) # type: ignore[operator]

Check warning on line 870 in ad/__init__.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Fix this call; Previous type checks suggest that "op" has type object and it is not callable.

See more on https://sonarcloud.io/project/issues?id=eggzec_ad&issues=AZ5BhaI3jwCU4LvpDRk9&open=AZ5BhaI3jwCU4LvpDRk9&pullRequest=24
if isinstance(a, np.ndarray) and not isinstance(b, np.ndarray):
return np.array( # type: ignore[call-overload]
[op(_to_py(xi), b) for xi in a.flat], # type: ignore[operator]

Check warning on line 873 in ad/__init__.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Fix this call; Previous type checks suggest that "op" has type object and it is not callable.

See more on https://sonarcloud.io/project/issues?id=eggzec_ad&issues=AZ5BhaI3jwCU4LvpDRk-&open=AZ5BhaI3jwCU4LvpDRk-&pullRequest=24
dtype=object,
).reshape(a.shape)
if not isinstance(a, np.ndarray) and isinstance(b, np.ndarray):
return np.array( # type: ignore[call-overload]
[op(a, _to_py(xi)) for xi in b.flat], # type: ignore[operator]

Check warning on line 878 in ad/__init__.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Fix this call; Previous type checks suggest that "op" has type object and it is not callable.

See more on https://sonarcloud.io/project/issues?id=eggzec_ad&issues=AZ5BhaI3jwCU4LvpDRk_&open=AZ5BhaI3jwCU4LvpDRk_&pullRequest=24
dtype=object,
).reshape(b.shape)
if isinstance(a, np.ndarray) and isinstance(b, np.ndarray):
return np.array( # type: ignore[call-overload]
[
op(_to_py(ai), _to_py(bi)) # type: ignore[operator]

Check warning on line 884 in ad/__init__.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Fix this call; Previous type checks suggest that "op" has type object and it is not callable.

See more on https://sonarcloud.io/project/issues?id=eggzec_ad&issues=AZ5BhaI3jwCU4LvpDRlA&open=AZ5BhaI3jwCU4LvpDRlA&pullRequest=24
for ai, bi in zip(a.flat, b.flat, strict=False)
],
dtype=object,
).reshape(a.shape)
return op(_to_py(a), _to_py(b)) # type: ignore[operator]

Check warning on line 889 in ad/__init__.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Fix this call; Previous type checks suggest that "op" has type object and it is not callable.

See more on https://sonarcloud.io/project/issues?id=eggzec_ad&issues=AZ5BhaI3jwCU4LvpDRlB&open=AZ5BhaI3jwCU4LvpDRlB&pullRequest=24

result = _apply(arith_op, *inputs)
out = kwargs.get("out")
if out is not None:
out[0][...] = result
return result


class ADV(ADF):
"""
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ select = [

ignore = []

[tool.ruff.lint.pylint]
max-public-methods = 31

[tool.ruff.lint.per-file-ignores]
"**/__init__.py" = ["RUF067"]
"tests/*.py" = []
Expand Down
Loading