Coverage for src/chebpy/_ufuncs.py: 100%

14 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-22 21:50 +0000

1"""Registration of elementwise NumPy ufunc methods on :class:`~chebpy.chebfun.Chebfun`. 

2 

3Kept separate from :mod:`chebpy.chebfun` so the ufunc boilerplate does not 

4bloat the main class. :func:`register_ufuncs` is called once, after the class 

5is defined, to attach ``sin``, ``cos``, ``exp``, ... methods that apply the 

6corresponding NumPy ufunc piecewise. 

7""" 

8 

9from __future__ import annotations 

10 

11from typing import TYPE_CHECKING, Any 

12 

13import numpy as np 

14 

15from .decorators import self_empty 

16 

17if TYPE_CHECKING: 

18 from .chebfun import Chebfun 

19 

20_UFUNCS = ( 

21 np.arccos, 

22 np.arccosh, 

23 np.arcsin, 

24 np.arcsinh, 

25 np.arctan, 

26 np.arctanh, 

27 np.cos, 

28 np.cosh, 

29 np.exp, 

30 np.exp2, 

31 np.expm1, 

32 np.log, 

33 np.log2, 

34 np.log10, 

35 np.log1p, 

36 np.sinh, 

37 np.sin, 

38 np.tan, 

39 np.tanh, 

40 np.sqrt, 

41) 

42 

43 

44def _add_ufunc(cls: type, op: Any) -> None: 

45 """Attach a single NumPy ufunc *op* as an elementwise method on *cls*.""" 

46 

47 @self_empty() 

48 def method(self: Chebfun) -> Chebfun: 

49 """Apply a NumPy universal function to each piece of this Chebfun. 

50 

51 Returns: 

52 Chebfun: A new Chebfun representing ``op(f(x))``. 

53 """ 

54 return self.__class__([op(fun) for fun in self]) 

55 

56 method.__name__ = op.__name__ 

57 setattr(cls, op.__name__, method) 

58 

59 

60def register_ufuncs(cls: type) -> None: 

61 """Attach an elementwise method for each supported NumPy ufunc to *cls*. 

62 

63 Args: 

64 cls: The :class:`~chebpy.chebfun.Chebfun` class to augment in place. 

65 """ 

66 for op in _UFUNCS: 

67 _add_ufunc(cls, op)