Skip to content
Snippets Groups Projects
core_operations.py 20.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • """
    B-ASIC Core Operations Module.
    
    
    Contains some of the most commonly used mathematical operations.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
    from typing import Dict, Optional
    
    from numpy import abs as np_abs
    from numpy import conjugate, sqrt
    
    from b_asic.graph_component import Name, TypeName
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
    from b_asic.operation import AbstractOperation
    from b_asic.port import SignalSourceProvider
    
    Frans Skarman's avatar
    Frans Skarman committed
    from b_asic.types import Num
    
    
    
    class Constant(AbstractOperation):
    
        Constant value operation.
    
    
        Gives a specified value that remains constant for every iteration.
    
    
        .. math:: y = \text{value}
    
        Parameters
        ==========
    
        value : Number, default: 0
            The constant value.
        name : Name, optional
            Operation name.
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        _execution_time = 0
    
    
    Frans Skarman's avatar
    Frans Skarman committed
        def __init__(self, value: Num = 0, name: Name = ""):
    
            """Construct a Constant operation with the given value."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=0,
                output_count=1,
    
    Frans Skarman's avatar
    Frans Skarman committed
                name=name,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                latency_offsets={"out0": 0},
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("c")
    
    
        def evaluate(self):
            return self.param("value")
    
        @property
    
    Frans Skarman's avatar
    Frans Skarman committed
        def value(self) -> Num:
    
            """Get the constant value of this operation."""
            return self.param("value")
    
        @value.setter
    
    Frans Skarman's avatar
    Frans Skarman committed
        def value(self, value: Num) -> None:
    
            """Set the constant value of this operation."""
    
            self.set_param("value", value)
    
    
    
    class Addition(AbstractOperation):
    
        """
        Binary addition operation.
    
        .. math:: y = x_0 + x_1
    
        Parameters
        ==========
    
        src0, src1 : SignalSourceProvider, optional
            The two signals to add.
        name : Name, optional
            Operation name.
        latency : int, optional
            Operation latency (delay from input to output in time units).
        latency_offsets : dict[str, int], optional
            Used if inputs have different arrival times, e.g.,
            ``{"in0": 0, "in1": 1}`` which corresponds to *src1* arriving one
            time unit later than *src0*. If not provided and *latency* is
            provided, set to zero if not explicitly provided. So the previous
            example can be written as ``{"in1": 1}`` only.
        execution_time : int, optional
            Operation execution time (time units before operator can be
            reused).
    
        See also
        ========
        AddSub
    
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
            """
            Construct an Addition operation.
            """
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("add")
    
    
        def evaluate(self, a, b):
            return a + b
    
    
    class Subtraction(AbstractOperation):
    
        """
        Binary subtraction operation.
    
    
        Gives the result of subtracting the second input from the first one.
    
    
        .. math:: y = x_0 - x_1
    
        Parameters
        ==========
    
        src0, src1 : SignalSourceProvider, optional
            The two signals to subtract.
        name : Name, optional
            Operation name.
        latency : int, optional
            Operation latency (delay from input to output in time units).
        latency_offsets : dict[str, int], optional
            Used if inputs have different arrival times, e.g.,
            ``{"in0": 0, "in1": 1}`` which corresponds to *src1* arriving one
            time unit later than *src0*. If not provided and *latency* is
            provided, set to zero if not explicitly provided. So the previous
            example can be written as ``{"in1": 1}`` only.
        execution_time : int, optional
            Operation execution time (time units before operator can be
            reused).
    
        See also
        ========
        AddSub
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("sub")
    
    
        def evaluate(self, a, b):
            return a - b
    
    
    
    class AddSub(AbstractOperation):
    
        Two-input addition or subtraction operation.
    
    
        Gives the result of adding or subtracting two inputs.
    
    
        .. math::
            y = \begin{cases}
            x_0 + x_1,& \text{is_add} = \text{True}\\
            x_0 - x_1,& \text{is_add} = \text{False}
            \end{cases}
    
        This is used to later map additions and subtractions to the same
        operator.
    
        Parameters
        ==========
    
        is_add : bool, default: True
            If True, the operation is an addition, if False, a subtraction.
        src0, src1 : SignalSourceProvider, optional
            The two signals to add or subtract.
        name : Name, optional
            Operation name.
        latency : int, optional
            Operation latency (delay from input to output in time units).
        latency_offsets : dict[str, int], optional
            Used if inputs have different arrival times, e.g.,
            ``{"in0": 0, "in1": 1}`` which corresponds to *src1* arriving one
            time unit later than *src0*. If not provided and *latency* is
            provided, set to zero if not explicitly provided. So the previous
            example can be written as ``{"in1": 1}`` only.
        execution_time : int, optional
            Operation execution time (time units before operator can be
            reused).
    
        See also
        ========
        Addition, Subtraction
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            is_add: bool = True,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
            """Construct an Addition/Subtraction operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
            self.set_param("is_add", is_add)
    
        @classmethod
        def type_name(cls) -> TypeName:
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("addsub")
    
    
        def evaluate(self, a, b):
            return a + b if self.is_add else a - b
    
        @property
    
    Frans Skarman's avatar
    Frans Skarman committed
        def is_add(self) -> Num:
    
            """Get if operation is an addition."""
    
            return self.param("is_add")
    
        @is_add.setter
        def is_add(self, is_add: bool) -> None:
    
            """Set if operation is an addition."""
    
            self.set_param("is_add", is_add)
    
    class Multiplication(AbstractOperation):
    
        Binary multiplication operation.
    
        .. math:: y = x_0 \times x_1
    
        Parameters
        ==========
    
        src0, src1 : SignalSourceProvider, optional
            The two signals to multiply.
        name : Name, optional
            Operation name.
        latency : int, optional
            Operation latency (delay from input to output in time units).
        latency_offsets : dict[str, int], optional
            Used if inputs have different arrival times, e.g.,
            ``{"in0": 0, "in1": 1}`` which corresponds to *src1* arriving one
            time unit later than *src0*. If not provided and *latency* is
            provided, set to zero if not explicitly provided. So the previous
            example can be written as ``{"in1": 1}`` only.
        execution_time : int, optional
            Operation execution time (time units before operator can be
            reused).
    
    
        See also
        ========
        ConstantMultiplication
    
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
            """Construct a Multiplication operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("mul")
    
    
        def evaluate(self, a, b):
            return a * b
    
    
    class Division(AbstractOperation):
    
        Binary division operation.
    
        Gives the result of dividing the first input by the second one.
    
        See also
        ========
        Reciprocal
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("div")
    
        Binary min operation.
    
        .. math:: y = \min\{x_0 , x_1\}
    
        .. note:: Only real-valued numbers are supported.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("min")
    
            if isinstance(a, complex) or isinstance(b, complex):
                raise ValueError(
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                    "core_operations.Min does not support complex numbers."
                )
    
    
    
    class Max(AbstractOperation):
    
        Binary max operation.
    
        .. math:: y = \max\{x_0 , x_1\}
    
        .. note:: Only real-valued numbers are supported.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("max")
    
    
        def evaluate(self, a, b):
    
            if isinstance(a, complex) or isinstance(b, complex):
                raise ValueError(
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                    "core_operations.Max does not support complex numbers."
                )
    
            return a if a > b else b
    
    
    
        Square root operation.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("sqrt")
    
        def evaluate(self, a):
            return sqrt(complex(a))
    
    class ComplexConjugate(AbstractOperation):
    
        """
        Complex conjugate operation.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
            """Construct a ComplexConjugate operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("conj")
    
    
        def evaluate(self, a):
    
        """
        Absolute value operation.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("abs")
    
    
        def evaluate(self, a):
    
    class ConstantMultiplication(AbstractOperation):
    
        Constant multiplication operation.
    
    
        Gives the result of multiplying its input by a specified value.
    
        .. math:: y = x_0 \times \text{value}
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
    
    Frans Skarman's avatar
    Frans Skarman committed
            value: Num = 0,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            src0: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
            """Construct a ConstantMultiplication operation with the given value.
            """
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=1,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("cmul")
    
    
        def evaluate(self, a):
    
    
        @property
    
    Frans Skarman's avatar
    Frans Skarman committed
        def value(self) -> Num:
    
            """Get the constant value of this operation."""
            return self.param("value")
    
        @value.setter
    
    Frans Skarman's avatar
    Frans Skarman committed
        def value(self, value: Num) -> None:
    
            """Set the constant value of this operation."""
    
            self.set_param("value", value)
    
        r"""
        Radix-2 Butterfly operation.
    
    
        Gives the result of adding its two inputs, as well as the result of
        subtracting the second input from the first one.
    
    
            y_0 & = & x_0 + x_1\\
            y_1 & = & x_0 - x_1
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=2,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("bfly")
    
        Multiply-add operation.
    
        Gives the result of multiplying the first input by the second input and
        then adding the third input.
    
        .. math:: y = x_0 \times x_1 + x_2
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
            src2: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=3,
                output_count=1,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1, src2],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("mad")
    
    
    
    class SymmetricTwoportAdaptor(AbstractOperation):
    
        Symmetric twoport-adaptor operation.
    
            y_0 & = & x_1 + \text{value}\times\left(x_1 - x_0\right)\\
            y_1 & = & x_0 + \text{value}\times\left(x_1 - x_0\right)
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        def __init__(
            self,
    
    Frans Skarman's avatar
    Frans Skarman committed
            value: Num = 0,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            src0: Optional[SignalSourceProvider] = None,
            src1: Optional[SignalSourceProvider] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            name: Name = Name(""),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
    
            execution_time: Optional[int] = None,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        ):
    
            """Construct a SymmetricTwoportAdaptor operation."""
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            super().__init__(
                input_count=2,
                output_count=2,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                name=Name(name),
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
                input_sources=[src0, src1],
                latency=latency,
                latency_offsets=latency_offsets,
    
                execution_time=execution_time,
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            )
    
            self.set_param("value", value)
    
        @classmethod
        def type_name(cls) -> TypeName:
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            return TypeName("sym2p")
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            tmp = self.value * (b - a)
    
            return b + tmp, a + tmp
    
        @property
    
    Frans Skarman's avatar
    Frans Skarman committed
        def value(self) -> Num:
    
            """Get the constant value of this operation."""
            return self.param("value")
    
        @value.setter
    
    Frans Skarman's avatar
    Frans Skarman committed
        def value(self, value: Num) -> None:
    
            """Set the constant value of this operation."""
    
            self.set_param("value", value)
    
    
    
    class Reciprocal(AbstractOperation):
        r"""
        Reciprocal operation.
    
        Gives the reciprocal of its input.
    
        .. math:: y = \frac{1}{x}
    
    
        See also
        ========
        Division
    
        """
    
        def __init__(
            self,
            src0: Optional[SignalSourceProvider] = None,
            name: Name = Name(""),
            latency: Optional[int] = None,
            latency_offsets: Optional[Dict[str, int]] = None,
            execution_time: Optional[int] = None,
        ):
    
            """Construct a Reciprocal operation."""
    
            super().__init__(
                input_count=1,
                output_count=1,
                name=Name(name),
                input_sources=[src0],
                latency=latency,
                latency_offsets=latency_offsets,
                execution_time=execution_time,
            )
    
        @classmethod
        def type_name(cls) -> TypeName:
            return TypeName("rec")
    
        def evaluate(self, a):
            return 1 / a