Skip to content
Snippets Groups Projects
core_operations.py 50.4 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.
    
        __slots__ = ("_value", "_name")
        _value: Num
        _name: Name
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        _execution_time = 0
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        is_linear = True
        is_constant = True
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
    
    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)
    
        @property
        def latency(self) -> int:
            return self.latency_offsets["out0"]
    
    
        def __repr__(self) -> str:
            return f"Constant({self.value})"
    
        def __str__(self) -> str:
            return f"{self.value}"
    
    
        def get_plot_coordinates(
            self,
        ) -> tuple[tuple[tuple[float, float], ...], tuple[tuple[float, float], ...]]:
            # Doc-string inherited
            return (
                (
                    (-0.5, 0),
                    (-0.5, 1),
                    (-0.25, 1),
                    (0, 0.5),
                    (-0.25, 0),
                    (-0.5, 0),
                ),
                (
                    (-0.5, 0),
                    (-0.5, 1),
                    (-0.25, 1),
                    (0, 0.5),
                    (-0.25, 0),
                    (-0.5, 0),
                ),
            )
    
        def get_input_coordinates(self) -> tuple[tuple[float, float], ...]:
            # doc-string inherited
            return tuple()
    
        def get_output_coordinates(self) -> tuple[tuple[float, float], ...]:
            # doc-string inherited
            return ((0, 0.5),)
    
    
    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
    
        __slots__ = (
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        is_linear = True
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
    
    
    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
        is_linear = True
    
    
        __slots__ = (
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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
    
    
        __slots__ = (
            "_is_add",
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _is_add: bool
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        is_linear = True
    
    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
    
        def is_add(self) -> bool:
    
            """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)
    
        @property
        def is_swappable(self) -> bool:
            return self.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
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            Used if inputs have different arrival times or if the inputs should arrive
            after the operator has stared. For example, ``{"in0": 0, "in1": 1}`` which
            corresponds to *src1* arriving one time unit later than *src0* and one time
            unit later than the operator starts. If not provided and *latency* is provided,
            set to zero. Hence, the previous example can be written as ``{"in1": 1}``
            only.
    
        execution_time : int, optional
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
            Operation execution time (time units before operator can be reused).
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        See Also
    
        ========
        ConstantMultiplication
    
    
        __slots__ = (
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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
    
    
        @property
        def is_linear(self) -> bool:
            return any(
    
                input_.connected_source.operation.is_constant for input_ in self.inputs
    
    
    class Division(AbstractOperation):
    
        Binary division operation.
    
        Gives the result of dividing the first input by the second one.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        Parameters
        ==========
    
        src0, src1 : SignalSourceProvider, optional
            The two signals to divide.
        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 or if the inputs should arrive
            after the operator has stared. For example, ``{"in0": 0, "in1": 1}`` which
            corresponds to *src1* arriving one time unit later than *src0* and one time
            unit later than the operator starts. If not provided and *latency* is provided,
            set to zero. Hence, 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
    
        ========
        Reciprocal
    
        __slots__ = (
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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")
    
        @property
        def is_linear(self) -> bool:
            return self.input(1).connected_source.operation.is_constant
    
    
        Binary min operation.
    
        .. math:: y = \min\{x_0 , x_1\}
    
        .. note:: Only real-valued numbers are supported.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        Parameters
        ==========
    
        src0, src1 : SignalSourceProvider, optional
            The two signals to determine the min of.
        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 or if the inputs should arrive
            after the operator has stared. For example, ``{"in0": 0, "in1": 1}`` which
            corresponds to *src1* arriving one time unit later than *src0* and one time
            unit later than the operator starts. If not provided and *latency* is provided,
            set to zero. Hence, 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
    
    
        __slots__ = (
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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("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
        Parameters
        ==========
    
        src0, src1 : SignalSourceProvider, optional
            The two signals to determine the min of.
        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 or if the inputs should arrive
            after the operator has stared. For example, ``{"in0": 0, "in1": 1}`` which
            corresponds to *src1* arriving one time unit later than *src0* and one time
            unit later than the operator starts. If not provided and *latency* is provided,
            set to zero. Hence, 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
    
    
        __slots__ = (
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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("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
    
        Parameters
        ----------
        src0 : :class:`~b_asic.port.SignalSourceProvider`, optional
            The signal to compute the square root of.
        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 input arrives later than when the operator starts, e.g.,
            ``{"in0": 0`` which corresponds to *src0* arriving one time unit after the
            operator starts. If not provided and *latency* is provided, set to zero.
        execution_time : int, optional
            Operation execution time (time units before operator can be reused).
    
        __slots__ = ("_src0", "_name", "_latency", "_latency_offsets", "_execution_time")
        _src0: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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
    
        Parameters
        ----------
        src0 : :class:`~b_asic.port.SignalSourceProvider`, optional
            The signal to compute the complex conjugate of.
        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 input arrives later than when the operator starts, e.g.,
            ``{"in0": 0`` which corresponds to *src0* arriving one time unit after the
            operator starts. If not provided and *latency* is provided, set to zero.
        execution_time : int, optional
            Operation execution time (time units before operator can be reused).
    
        __slots__ = ("_src0", "_name", "_latency", "_latency_offsets", "_execution_time")
        _src0: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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
    
        Parameters
        ----------
        src0 : :class:`~b_asic.port.SignalSourceProvider`, optional
            The signal to compute the absolute value of.
        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 input arrives later than when the operator starts, e.g.,
            ``{"in0": 0`` which corresponds to *src0* arriving one time unit after the
            operator starts. If not provided and *latency* is provided, set to zero.
        execution_time : int, optional
            Operation execution time (time units before operator can be reused).
    
        __slots__ = ("_src0", "_name", "_latency", "_latency_offsets", "_execution_time")
        _src0: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    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
    
        Parameters
        ----------
        value : int
            Value to multiply with.
        src0 : :class:`~b_asic.port.SignalSourceProvider`, optional
            The signal 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 input arrives later than when the operator starts, e.g.,
            ``{"in0": 0`` which corresponds to *src0* arriving one time unit after the
            operator starts. If not provided and *latency* is provided, set to zero.
        execution_time : int, optional
            Operation execution time (time units before operator can be reused).
    
        See Also
        --------
        Multiplication
    
    
        __slots__ = (
            "_value",
            "_src0",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _value: Num
        _src0: Optional[SignalSourceProvider]
        _name: Name
        _latency: Optional[int]
        _latency_offsets: Optional[Dict[str, int]]
        _execution_time: Optional[int]
    
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        is_linear = True
    
    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)
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        Radix-2 Butterfly operation for FFTs.
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
        Gives the result of adding its two inputs, as well as the result of subtracting the
        second input from the first one. This corresponds to a 2-point DFT.
    
            y_0 & = & x_0 + x_1\\
            y_1 & = & x_0 - x_1
    
    Oscar Gustafsson's avatar
    Oscar Gustafsson committed
    
        Parameters
        ==========
    
        src0, src1 : SignalSourceProvider, optional
            The two signals to compute the 2-point DFT of.
        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 or if the inputs should arrive
            after the operator has stared. For example, ``{"in0": 0, "in1": 1}`` which
            corresponds to *src1* arriving one time unit later than *src0* and one time
            unit later than the operator starts. If not provided and *latency* is provided,
            set to zero. Hence, the previous example can be written as ``{"in1": 1}``
            only.
        execution_time : int, optional
            Operation execution time (time units before operator can be reused).
    
    
        __slots__ = (
            "_src0",
            "_src1",
            "_name",
            "_latency",
            "_latency_offsets",
            "_execution_time",
        )
        _src0: Optional[SignalSourceProvider]
        _src1: Optional[SignalSourceProvider]
        _name: Name