diff --git a/b_asic/signal_generator.py b/b_asic/signal_generator.py index cf79873794d11435542d94ea0ac38ec198c4a4c4..7b25e586083d91366f24278c310227516e9e01e5 100644 --- a/b_asic/signal_generator.py +++ b/b_asic/signal_generator.py @@ -19,45 +19,53 @@ class SignalGenerator: def __call__(self, time: int) -> complex: raise NotImplementedError - def __add__(self, other) -> "AddGenerator": + def __add__(self, other) -> "_AddGenerator": if isinstance(other, Number): - return AddGenerator(self, Constant(other)) - return AddGenerator(self, other) + return _AddGenerator(self, Constant(other)) + if isinstance(other, SignalGenerator): + return _AddGenerator(self, other) + raise TypeError(f"Cannot add {other!r} to {type(self)}") - def __radd__(self, other) -> "AddGenerator": + def __radd__(self, other) -> "_AddGenerator": if isinstance(other, Number): - return AddGenerator(self, Constant(other)) - return AddGenerator(self, other) + return _AddGenerator(Constant(other), self) + raise TypeError(f"Cannot add {type(self)} to {other!r}") - def __sub__(self, other) -> "SubGenerator": + def __sub__(self, other) -> "_SubGenerator": if isinstance(other, Number): - return SubGenerator(self, Constant(other)) - return SubGenerator(self, other) + return _SubGenerator(self, Constant(other)) + if isinstance(other, SignalGenerator): + return _SubGenerator(self, other) + raise TypeError(f"Cannot subtract {other!r} from {type(self)}") - def __rsub__(self, other) -> "SubGenerator": + def __rsub__(self, other) -> "_SubGenerator": if isinstance(other, Number): - return SubGenerator(Constant(other), self) - return SubGenerator(other, self) + return _SubGenerator(Constant(other), self) + raise TypeError(f"Cannot subtract {type(self)} from {other!r}") - def __mul__(self, other) -> "MulGenerator": + def __mul__(self, other) -> "_MulGenerator": if isinstance(other, Number): - return MultGenerator(self, Constant(other)) - return MultGenerator(self, other) + return _MulGenerator(self, Constant(other)) + if isinstance(other, SignalGenerator): + return _MulGenerator(self, other) + raise TypeError(f"Cannot multiply {type(self)} with {other!r}") - def __rmul__(self, other) -> "MulGenerator": + def __rmul__(self, other) -> "_MulGenerator": if isinstance(other, Number): - return MultGenerator(self, Constant(other)) - return MultGenerator(self, other) + return _MulGenerator(Constant(other), self) + raise TypeError(f"Cannot multiply {other!r} with {type(self)}") - def __truediv__(self, other) -> "MulGenerator": + def __truediv__(self, other) -> "_DivGenerator": if isinstance(other, Number): - return DivGenerator(self, Constant(other)) - return DivGenerator(self, other) + return _DivGenerator(self, Constant(other)) + if isinstance(other, SignalGenerator): + return _DivGenerator(self, other) + raise TypeError(f"Cannot divide {type(self)} with {other!r}") - def __rtruediv__(self, other) -> "MulGenerator": + def __rtruediv__(self, other) -> "_DivGenerator": if isinstance(other, Number): - return DivGenerator(Constant(other), self) - return DivGenerator(other, self) + return _DivGenerator(Constant(other), self) + raise TypeError(f"Cannot divide {other!r} with {type(self)}") class Impulse(SignalGenerator): @@ -70,7 +78,7 @@ class Impulse(SignalGenerator): The delay before the signal goes to 1 for one sample. """ - def __init__(self, delay: int = 0) -> Callable[[int], complex]: + def __init__(self, delay: int = 0) -> None: self._delay = delay def __call__(self, time: int) -> complex: @@ -90,7 +98,7 @@ class Step(SignalGenerator): The delay before the signal goes to 1. """ - def __init__(self, delay: int = 0) -> Callable[[int], complex]: + def __init__(self, delay: int = 0) -> None: self._delay = delay def __call__(self, time: int) -> complex: @@ -110,7 +118,7 @@ class Constant(SignalGenerator): The constant. """ - def __init__(self, constant: complex = 1.0) -> Callable[[int], complex]: + def __init__(self, constant: complex = 1.0) -> None: self._constant = constant def __call__(self, time: int) -> complex: @@ -130,7 +138,7 @@ class ZeroPad(SignalGenerator): The data that should be padded. """ - def __init__(self, data: Sequence[complex]) -> Callable[[int], complex]: + def __init__(self, data: Sequence[complex]) -> None: self._data = data self._len = len(data) @@ -156,9 +164,7 @@ class Sinusoid(SignalGenerator): The normalized phase offset. """ - def __init__( - self, frequency: float, phase: float = 0.0 - ) -> Callable[[int], complex]: + def __init__(self, frequency: float, phase: float = 0.0) -> None: self._frequency = frequency self._phase = phase @@ -173,95 +179,87 @@ class Sinusoid(SignalGenerator): ) -class AddGenerator: +class _AddGenerator(SignalGenerator): """ Signal generator that adds two signals. """ - def __init__( - self, a: SignalGenerator, b: SignalGenerator - ) -> Callable[[int], complex]: + def __init__(self, a: SignalGenerator, b: SignalGenerator) -> None: self._a = a self._b = b def __call__(self, time: int) -> complex: return self._a(time) + self._b(time) - def __str__(self): + def __repr__(self): return f"{self._a} + {self._b}" -class SubGenerator: +class _SubGenerator(SignalGenerator): """ Signal generator that subtracts two signals. """ - def __init__( - self, a: SignalGenerator, b: SignalGenerator - ) -> Callable[[int], complex]: + def __init__(self, a: SignalGenerator, b: SignalGenerator) -> None: self._a = a self._b = b def __call__(self, time: int) -> complex: return self._a(time) - self._b(time) - def __str__(self): + def __repr__(self): return f"{self._a} - {self._b}" -class MultGenerator: +class _MulGenerator(SignalGenerator): """ Signal generator that multiplies two signals. """ - def __init__( - self, a: SignalGenerator, b: SignalGenerator - ) -> Callable[[int], complex]: + def __init__(self, a: SignalGenerator, b: SignalGenerator) -> None: self._a = a self._b = b def __call__(self, time: int) -> complex: return self._a(time) * self._b(time) - def __str__(self): + def __repr__(self): a = ( f"({self._a})" - if isinstance(self._a, (AddGenerator, SubGenerator)) + if isinstance(self._a, (_AddGenerator, _SubGenerator)) else f"{self._a}" ) b = ( f"({self._b})" - if isinstance(self._b, (AddGenerator, SubGenerator)) + if isinstance(self._b, (_AddGenerator, _SubGenerator)) else f"{self._b}" ) return f"{a} * {b}" -class DivGenerator: +class _DivGenerator(SignalGenerator): """ Signal generator that divides two signals. """ - def __init__( - self, a: SignalGenerator, b: SignalGenerator - ) -> Callable[[int], complex]: + def __init__(self, a: SignalGenerator, b: SignalGenerator) -> None: self._a = a self._b = b def __call__(self, time: int) -> complex: return self._a(time) / self._b(time) - def __str__(self): + def __repr__(self): a = ( f"({self._a})" - if isinstance(self._a, (AddGenerator, SubGenerator)) + if isinstance(self._a, (_AddGenerator, _SubGenerator)) else f"{self._a}" ) b = ( f"({self._b})" if isinstance( self._b, - (AddGenerator, SubGenerator, MultGenerator, DivGenerator), + (_AddGenerator, _SubGenerator, _MulGenerator, _DivGenerator), ) else f"{self._b}" ) diff --git a/test/test_signal_generator.py b/test/test_signal_generator.py index 085b555a597c0f5233d3d700b962f82080bfbda9..e11423bdca9dde748e7e9732d4b96035629a4655 100644 --- a/test/test_signal_generator.py +++ b/test/test_signal_generator.py @@ -2,7 +2,17 @@ from math import sqrt import pytest -from b_asic.signal_generator import Constant, Impulse, Sinusoid, Step, ZeroPad +from b_asic.signal_generator import ( + Constant, + Impulse, + Sinusoid, + Step, + ZeroPad, + _AddGenerator, + _DivGenerator, + _MulGenerator, + _SubGenerator, +) def test_impulse(): @@ -96,6 +106,7 @@ def test_addition(): assert g(3) == 0 assert str(g) == "Impulse() + Impulse(2)" + assert isinstance(g, _AddGenerator) g = 1.0 + Impulse(2) assert g(-1) == 1 @@ -104,7 +115,8 @@ def test_addition(): assert g(2) == 2 assert g(3) == 1 - assert str(g) == "Impulse(2) + 1.0" + assert str(g) == "1.0 + Impulse(2)" + assert isinstance(g, _AddGenerator) g = Impulse(1) + 1.0 assert g(-1) == 1 @@ -114,6 +126,7 @@ def test_addition(): assert g(3) == 1 assert str(g) == "Impulse(1) + 1.0" + assert isinstance(g, _AddGenerator) def test_subtraction(): @@ -125,6 +138,7 @@ def test_subtraction(): assert g(3) == 0 assert str(g) == "Impulse() - Impulse(2)" + assert isinstance(g, _SubGenerator) g = 1.0 - Impulse(2) assert g(-1) == 1 @@ -134,6 +148,7 @@ def test_subtraction(): assert g(3) == 1 assert str(g) == "1.0 - Impulse(2)" + assert isinstance(g, _SubGenerator) g = Impulse(2) - 1.0 assert g(-1) == -1 @@ -143,6 +158,7 @@ def test_subtraction(): assert g(3) == -1 assert str(g) == "Impulse(2) - 1.0" + assert isinstance(g, _SubGenerator) def test_multiplication(): @@ -153,6 +169,7 @@ def test_multiplication(): assert g(2) == 0 assert str(g) == "Impulse() * 0.5" + assert isinstance(g, _MulGenerator) g = 2 * Sinusoid(0.5, 0.25) assert g(0) == pytest.approx(sqrt(2)) @@ -160,7 +177,8 @@ def test_multiplication(): assert g(2) == pytest.approx(-sqrt(2)) assert g(3) == pytest.approx(-sqrt(2)) - assert str(g) == "Sinusoid(0.5, 0.25) * 2" + assert str(g) == "2 * Sinusoid(0.5, 0.25)" + assert isinstance(g, _MulGenerator) g = Step(1) * (Sinusoid(0.5, 0.25) + 1.0) assert g(0) == 0 @@ -169,6 +187,7 @@ def test_multiplication(): assert g(3) == pytest.approx(-sqrt(2) / 2 + 1) assert str(g) == "Step(1) * (Sinusoid(0.5, 0.25) + 1.0)" + assert isinstance(g, _MulGenerator) def test_division(): @@ -179,6 +198,7 @@ def test_division(): assert g(2) == 0.5 assert str(g) == "Step() / 2" + assert isinstance(g, _DivGenerator) g = 0.5 / Step() assert g(0) == 0.5 @@ -186,6 +206,7 @@ def test_division(): assert g(2) == 0.5 assert str(g) == "0.5 / Step()" + assert isinstance(g, _DivGenerator) g = Sinusoid(0.5, 0.25) / (0.5 * Step()) assert g(0) == pytest.approx(sqrt(2)) @@ -193,4 +214,5 @@ def test_division(): assert g(2) == pytest.approx(-sqrt(2)) assert g(3) == pytest.approx(-sqrt(2)) - assert str(g) == "Sinusoid(0.5, 0.25) / (Step() * 0.5)" + assert str(g) == "Sinusoid(0.5, 0.25) / (0.5 * Step())" + assert isinstance(g, _DivGenerator)