Newer
Older
Angus Lothian
committed
Contains some of the most commonly used mathematical operations.
from typing import Dict, Optional
from numpy import abs as np_abs
from numpy import conjugate, sqrt
Angus Lothian
committed
from b_asic.graph_component import Name, TypeName
from b_asic.operation import AbstractOperation
from b_asic.port import SignalSourceProvider
Angus Lothian
committed
Gives a specified value that remains constant for every iteration.
output(0): self.param("value")
def __init__(self, value: Number = 0, name: Name = ""):
Angus Lothian
committed
"""Construct a Constant operation with the given value."""
super().__init__(
input_count=0,
output_count=1,
name=name,
latency_offsets={"out0": 0},
)
Angus Lothian
committed
self.set_param("value", value)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "c"
def evaluate(self):
return self.param("value")
@property
Angus Lothian
committed
def value(self) -> Number:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Number) -> None:
"""Set the constant value of this operation."""
Angus Lothian
committed
Gives the result of adding two inputs.
output(0): input(0) + input(1)
"""
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct an Addition operation."""
super().__init__(
input_count=2,
output_count=1,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "add"
def evaluate(self, a, b):
return a + b
class Subtraction(AbstractOperation):
Angus Lothian
committed
Gives the result of subtracting the second input from the first one.
output(0): input(0) - input(1)
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a Subtraction operation."""
super().__init__(
input_count=2,
output_count=1,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "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.
output(0): input(0) + input(1) if is_add = True
output(0): input(0) - input(1) if is_add = False
"""
def __init__(
self,
is_add: bool = True,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
"""Construct an Addition operation."""
super().__init__(
input_count=2,
output_count=1,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
self.set_param("is_add", is_add)
@classmethod
def type_name(cls) -> TypeName:
return "addsub"
def evaluate(self, a, b):
return a + b if self.is_add else a - b
@property
def is_add(self) -> Number:
"""Get if operation is add."""
return self.param("is_add")
@is_add.setter
def is_add(self, is_add: bool) -> None:
"""Set if operation is add."""
Angus Lothian
committed
Gives the result of multiplying two inputs.
output(0): input(0) * input(1)
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a Multiplication operation."""
super().__init__(
input_count=2,
output_count=1,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "mul"
def evaluate(self, a, b):
return a * b
class Division(AbstractOperation):
Angus Lothian
committed
Gives the result of dividing the first input by the second one.
Angus Lothian
committed
output(0): input(0) / input(1)
"""
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a Division operation."""
super().__init__(
input_count=2,
output_count=1,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
Angus Lothian
committed
def evaluate(self, a, b):
return a / b
Angus Lothian
committed
class Min(AbstractOperation):
Angus Lothian
committed
Gives the minimum value of two inputs.
NOTE: Non-real numbers are not supported.
Angus Lothian
committed
output(0): min(input(0), input(1))
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a Min operation."""
super().__init__(
input_count=2,
output_count=1,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "min"
Angus Lothian
committed
def evaluate(self, a, b):
if isinstance(a, complex) or isinstance(b, complex):
raise ValueError(
"core_operations.Min does not support complex numbers.")
Angus Lothian
committed
return a if a < b else b
Angus Lothian
committed
Gives the maximum value of two inputs.
NOTE: Non-real numbers are not supported.
output(0): max(input(0), input(1))
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a Max operation."""
super().__init__(
input_count=2,
output_count=1,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "max"
if isinstance(a, complex) or isinstance(b, complex):
raise ValueError(
"core_operations.Max does not support complex numbers.")
Angus Lothian
committed
class SquareRoot(AbstractOperation):
Angus Lothian
committed
Gives the square root of its input.
output(0): sqrt(input(0))
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a SquareRoot operation."""
super().__init__(
input_count=1,
output_count=1,
name=name,
input_sources=[src0],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "sqrt"
Angus Lothian
committed
def evaluate(self, a):
return sqrt(complex(a))
Angus Lothian
committed
class ComplexConjugate(AbstractOperation):
Angus Lothian
committed
Gives the complex conjugate of its input.
output(0): conj(input(0))
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a ComplexConjugate operation."""
super().__init__(
input_count=1,
output_count=1,
name=name,
input_sources=[src0],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "conj"
Angus Lothian
committed
return conjugate(a)
Angus Lothian
committed
class Absolute(AbstractOperation):
Angus Lothian
committed
Gives the absolute value of its input.
output(0): abs(input(0))
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct an Absolute operation."""
super().__init__(
input_count=1,
output_count=1,
name=name,
input_sources=[src0],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "abs"
Angus Lothian
committed
return np_abs(a)
Angus Lothian
committed
class ConstantMultiplication(AbstractOperation):
Angus Lothian
committed
Gives the result of multiplying its input by a specified value.
Angus Lothian
committed
output(0): self.param("value") * input(0)
def __init__(
self,
value: Number = 0,
src0: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
"""Construct a ConstantMultiplication operation with the given value.
"""
super().__init__(
input_count=1,
output_count=1,
name=name,
input_sources=[src0],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
self.set_param("value", value)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "cmul"
Angus Lothian
committed
return a * self.param("value")
Angus Lothian
committed
def value(self) -> Number:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Number) -> None:
"""Set the constant value of this operation."""
Angus Lothian
committed
class Butterfly(AbstractOperation):
Angus Lothian
committed
Gives the result of adding its two inputs, as well as the result of
subtracting the second input from the first one.
output(0): input(0) + input(1)
output(1): input(0) - input(1)
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a Butterfly operation."""
super().__init__(
input_count=2,
output_count=2,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "bfly"
Angus Lothian
committed
def evaluate(self, a, b):
return a + b, a - b
Angus Lothian
committed
class MAD(AbstractOperation):
Angus Lothian
committed
Gives the result of multiplying the first input by the second input and
then adding the third input.
Angus Lothian
committed
output(0): (input(0) * input(1)) + input(2)
"""
def __init__(
self,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
src2: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
Angus Lothian
committed
"""Construct a MAD operation."""
super().__init__(
input_count=3,
output_count=1,
name=name,
input_sources=[src0, src1, src2],
latency=latency,
latency_offsets=latency_offsets,
)
Angus Lothian
committed
@classmethod
def type_name(cls) -> TypeName:
return "mad"
Angus Lothian
committed
def evaluate(self, a, b, c):
return a * b + c
class SymmetricTwoportAdaptor(AbstractOperation):
"""
Symmetric twoport-adaptor operation.
output(0): input(1) + value*(input(1) - input(0)
output(1): input(0) + value*(input(1) - input(0)
"""
def __init__(
self,
value: Number = 0,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = "",
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
):
"""Construct a Butterfly operation."""
super().__init__(
input_count=2,
output_count=2,
name=name,
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
)
self.set_param("value", value)
@classmethod
def type_name(cls) -> TypeName:
return "sym2p"
def evaluate(self, a, b):
return b + tmp, a + tmp
@property
def value(self) -> Number:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Number) -> None:
"""Set the constant value of this operation."""