Coverage for physioblocks / base / operators.py: 98%
82 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-09 16:40 +0100
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-09 16:40 +0100
1# SPDX-FileCopyrightText: Copyright INRIA
2#
3# SPDX-License-Identifier: LGPL-3.0-only
4#
5# Copyright INRIA
6#
7# This file is part of PhysioBlocks, a library mostly developed by the
8# [Ananke project-team](https://team.inria.fr/ananke) at INRIA.
9#
10# Authors:
11# - Colin Drieu
12# - Dominique Chapelle
13# - François Kimmig
14# - Philippe Moireau
15#
16# PhysioBlocks is free software: you can redistribute it and/or modify it under the
17# terms of the GNU Lesser General Public License as published by the Free Software
18# Foundation, version 3 of the License.
19#
20# PhysioBlocks is distributed in the hope that it will be useful, but WITHOUT ANY
21# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
22# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
23#
24# You should have received a copy of the GNU Lesser General Public License along with
25# PhysioBlocks. If not, see <https://www.gnu.org/licenses/>.
27"""Define base classe to provide generic base operators"""
29from abc import ABC, abstractmethod
30from typing import Any
32import numpy as np
33from numpy.typing import NDArray
36class AbstractBaseOperators(ABC):
37 """Base class defining behaviors for common operators
39 The derived classes should implement the :attr:`operation_value` property
40 to return the attribute of the class that will be used with base
41 operators.
42 """
44 @property
45 @abstractmethod
46 def operation_value(self) -> Any:
47 """
48 Overwrite in derived class to return the value used by the
49 class for the base operators.
50 """
51 raise NotImplementedError(
52 str.format(
53 "{0} is not implemented in {1} class.",
54 AbstractBaseOperators.operation_value.__name__,
55 type(self),
56 )
57 )
59 # Convertion
61 def __float__(self) -> float:
62 return float(self.operation_value)
64 def __array__(
65 self, dtype: type | None = None, copy: bool | None = None
66 ) -> NDArray[Any]:
67 return np.asarray(self.operation_value, dtype=dtype, copy=copy)
69 # Compare
71 # Equality
72 def __eq__(self, other: Any) -> bool:
73 compared_value = (
74 other.operation_value if isinstance(other, type(self)) else other
75 )
76 return bool(self.operation_value == compared_value)
78 # Greater
79 def __ge__(self, other: Any) -> bool:
80 if isinstance(other, type(self)):
81 return bool(self.operation_value >= other.operation_value)
82 return bool(self.operation_value >= other)
84 def __gt__(self, other: Any) -> bool:
85 if isinstance(other, type(self)):
86 return bool(self.operation_value > other.operation_value)
87 return bool(self.operation_value > other)
89 # Lesser
90 def __le__(self, other: Any) -> bool:
91 if isinstance(other, type(self)):
92 return bool(self.operation_value <= other.operation_value)
93 return bool(self.operation_value <= other)
95 def __lt__(self, other: Any) -> bool:
96 if isinstance(other, type(self)):
97 return bool(self.operation_value < other.operation_value)
98 return bool(self.operation_value < other)
100 # Base Operations
102 # Sum
103 def __add__(self, other: Any) -> Any:
104 if isinstance(other, type(self)):
105 return self.operation_value + other.operation_value
106 return self.operation_value + other
108 def __radd__(self, other: Any) -> Any:
109 return other + self.operation_value
111 # Subtraction
112 def __sub__(self, other: Any) -> Any:
113 if isinstance(other, type(self)):
114 return self.operation_value - other.operation_value
115 return self.operation_value - other
117 def __rsub__(self, other: Any) -> Any:
118 return other - self.operation_value
120 # Oposite
121 def __neg__(self) -> Any:
122 return -self.operation_value
124 # Multiplication
125 def __mul__(self, other: Any) -> Any:
126 if isinstance(other, type(self)):
127 return self.operation_value * other.operation_value
128 return self.operation_value * other
130 def __rmul__(self, other: Any) -> Any:
131 return other * self.operation_value
133 # MatMul
134 def __matmul__(self, other: Any) -> Any:
135 if isinstance(other, type(self)):
136 return self.operation_value @ other.operation_value
137 return self.operation_value @ other
139 def __rmatmul__(self, other: Any) -> Any:
140 return other @ self.operation_value
142 # Division
143 def __truediv__(self, other: Any) -> Any:
144 if isinstance(other, type(self)):
145 return self.operation_value / other.operation_value
146 return self.operation_value / other
148 def __rtruediv__(self, other: Any) -> Any:
149 return other / self.operation_value
151 # Floor Division
152 def __floordiv__(self, other: Any) -> Any:
153 if isinstance(other, type(self)):
154 return self.operation_value // other.operation_value
155 return self.operation_value // other
157 def __rfloordiv__(self, other: Any) -> Any:
158 return other // self.operation_value
160 # Modulo
161 def __mod__(self, other: Any) -> Any:
162 if isinstance(other, type(self)):
163 return self.operation_value % other.operation_value
164 return self.operation_value % other
166 def __rmod__(self, other: Any) -> Any:
167 return other % self.operation_value
169 # Power
170 def __pow__(self, other: Any) -> Any:
171 if isinstance(other, type(self)):
172 return self.operation_value**other.operation_value
173 return self.operation_value**other
175 def __rpow__(self, other: Any) -> Any:
176 return other**self.operation_value