mirror of https://github.com/Nonannet/copapy.git
"variable" type renamed to "value"
This commit is contained in:
parent
423ca30ac6
commit
2e48fe5ec2
|
|
@ -1,5 +1,5 @@
|
||||||
from ._target import Target
|
from ._target import Target
|
||||||
from ._basic_types import NumLike, variable, generic_sdb, iif
|
from ._basic_types import NumLike, value, generic_sdb, iif
|
||||||
from ._vectors import vector, distance, scalar_projection, angle_between, rotate_vector, vector_projection
|
from ._vectors import vector, distance, scalar_projection, angle_between, rotate_vector, vector_projection
|
||||||
from ._matrices import matrix, identity, zeros, ones, diagonal, eye
|
from ._matrices import matrix, identity, zeros, ones, diagonal, eye
|
||||||
from ._math import sqrt, abs, sign, sin, cos, tan, asin, acos, atan, atan2, log, exp, pow, get_42, clamp, min, max, relu
|
from ._math import sqrt, abs, sign, sin, cos, tan, asin, acos, atan, atan2, log, exp, pow, get_42, clamp, min, max, relu
|
||||||
|
|
@ -8,7 +8,7 @@ from ._autograd import grad
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Target",
|
"Target",
|
||||||
"NumLike",
|
"NumLike",
|
||||||
"variable",
|
"value",
|
||||||
"generic_sdb",
|
"generic_sdb",
|
||||||
"iif",
|
"iif",
|
||||||
"vector",
|
"vector",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from . import variable, vector, matrix
|
from . import value, vector, matrix
|
||||||
import copapy.backend as cpb
|
import copapy.backend as cpb
|
||||||
from typing import Any, Sequence, overload
|
from typing import Any, Sequence, overload
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
|
|
@ -6,14 +6,14 @@ from ._basic_types import Net, unifloat
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def grad(x: Any, y: variable[Any]) -> unifloat: ...
|
def grad(x: Any, y: value[Any]) -> unifloat: ...
|
||||||
@overload
|
@overload
|
||||||
def grad(x: Any, y: vector[Any]) -> vector[float]: ...
|
def grad(x: Any, y: vector[Any]) -> vector[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def grad(x: Any, y: Sequence[variable[Any]]) -> list[unifloat]: ...
|
def grad(x: Any, y: Sequence[value[Any]]) -> list[unifloat]: ...
|
||||||
@overload
|
@overload
|
||||||
def grad(x: Any, y: matrix[Any]) -> matrix[float]: ...
|
def grad(x: Any, y: matrix[Any]) -> matrix[float]: ...
|
||||||
def grad(x: Any, y: variable[Any] | Sequence[variable[Any]] | vector[Any] | matrix[Any]) -> Any:
|
def grad(x: Any, y: value[Any] | Sequence[value[Any]] | vector[Any] | matrix[Any]) -> Any:
|
||||||
"""Returns the partial derivative dx/dy where x needs to be a scalar
|
"""Returns the partial derivative dx/dy where x needs to be a scalar
|
||||||
and y might be a scalar, a list of scalars, a vector or matrix.
|
and y might be a scalar, a list of scalars, a vector or matrix.
|
||||||
|
|
||||||
|
|
@ -24,9 +24,9 @@ def grad(x: Any, y: variable[Any] | Sequence[variable[Any]] | vector[Any] | matr
|
||||||
Returns:
|
Returns:
|
||||||
Derivative of x with the type and dimensions of y
|
Derivative of x with the type and dimensions of y
|
||||||
"""
|
"""
|
||||||
assert isinstance(x, variable), f"Argument x for grad function must be a variable but is {type(x)}."
|
assert isinstance(x, value), f"Argument x for grad function must be a copapy value but is {type(x)}."
|
||||||
|
|
||||||
if isinstance(y, variable):
|
if isinstance(y, value):
|
||||||
y_set = {y}
|
y_set = {y}
|
||||||
if isinstance(y, matrix):
|
if isinstance(y, matrix):
|
||||||
y_set = {v for row in y for v in row}
|
y_set = {v for row in y for v in row}
|
||||||
|
|
@ -40,7 +40,7 @@ def grad(x: Any, y: variable[Any] | Sequence[variable[Any]] | vector[Any] | matr
|
||||||
net_lookup = {net.source: net for node in ordered_ops for net in node.args}
|
net_lookup = {net.source: net for node in ordered_ops for net in node.args}
|
||||||
grad_dict: dict[Net, unifloat] = dict()
|
grad_dict: dict[Net, unifloat] = dict()
|
||||||
|
|
||||||
def add_grad(val: variable[Any], gradient_value: unifloat) -> None:
|
def add_grad(val: value[Any], gradient_value: unifloat) -> None:
|
||||||
grad_dict[val] = grad_dict.get(val, 0.0) + gradient_value
|
grad_dict[val] = grad_dict.get(val, 0.0) + gradient_value
|
||||||
|
|
||||||
for node in reversed(ordered_ops):
|
for node in reversed(ordered_ops):
|
||||||
|
|
@ -49,8 +49,8 @@ def grad(x: Any, y: variable[Any] | Sequence[variable[Any]] | vector[Any] | matr
|
||||||
args: Sequence[Any] = list(node.args)
|
args: Sequence[Any] = list(node.args)
|
||||||
g = 1.0 if node is x.source else grad_dict[net_lookup[node]]
|
g = 1.0 if node is x.source else grad_dict[net_lookup[node]]
|
||||||
opn = node.name.split('_')[0]
|
opn = node.name.split('_')[0]
|
||||||
a: variable[Any] = args[0]
|
a: value[Any] = args[0]
|
||||||
b: variable[Any] = args[1] if len(args) > 1 else a
|
b: value[Any] = args[1] if len(args) > 1 else a
|
||||||
|
|
||||||
if opn in ['ge', 'gt', 'eq', 'ne', 'floordiv', 'bwand', 'bwor', 'bwxor']:
|
if opn in ['ge', 'gt', 'eq', 'ne', 'floordiv', 'bwand', 'bwor', 'bwxor']:
|
||||||
pass # Derivative is 0 for all ops returning integers
|
pass # Derivative is 0 for all ops returning integers
|
||||||
|
|
@ -117,10 +117,10 @@ def grad(x: Any, y: variable[Any] | Sequence[variable[Any]] | vector[Any] | matr
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Operation {opn} not yet supported for auto diff.")
|
raise ValueError(f"Operation {opn} not yet supported for auto diff.")
|
||||||
|
|
||||||
if isinstance(y, variable):
|
if isinstance(y, value):
|
||||||
return grad_dict[y]
|
return grad_dict[y]
|
||||||
if isinstance(y, vector):
|
if isinstance(y, vector):
|
||||||
return vector(grad_dict[yi] if isinstance(yi, variable) else 0.0 for yi in y)
|
return vector(grad_dict[yi] if isinstance(yi, value) else 0.0 for yi in y)
|
||||||
if isinstance(y, matrix):
|
if isinstance(y, matrix):
|
||||||
return matrix((grad_dict[yi] if isinstance(yi, variable) else 0.0 for yi in row) for row in y)
|
return matrix((grad_dict[yi] if isinstance(yi, value) else 0.0 for yi in row) for row in y)
|
||||||
return [grad_dict[yi] for yi in y]
|
return [grad_dict[yi] for yi in y]
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ from ._stencils import stencil_database, detect_process_arch
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
from ._helper_types import TNum
|
from ._helper_types import TNum
|
||||||
|
|
||||||
NumLike: TypeAlias = 'variable[int] | variable[float] | int | float'
|
NumLike: TypeAlias = 'value[int] | value[float] | int | float'
|
||||||
unifloat: TypeAlias = 'variable[float] | float'
|
unifloat: TypeAlias = 'value[float] | float'
|
||||||
uniint: TypeAlias = 'variable[int] | int'
|
uniint: TypeAlias = 'value[int] | int'
|
||||||
|
|
||||||
TCPNum = TypeVar("TCPNum", bound='variable[Any]')
|
TCPNum = TypeVar("TCPNum", bound='value[Any]')
|
||||||
TVarNumb: TypeAlias = 'variable[Any] | int | float'
|
TVarNumb: TypeAlias = 'value[Any] | int | float'
|
||||||
|
|
||||||
stencil_cache: dict[tuple[str, str], stencil_database] = {}
|
stencil_cache: dict[tuple[str, str], stencil_database] = {}
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ class Node:
|
||||||
|
|
||||||
|
|
||||||
class Net:
|
class Net:
|
||||||
"""A Net represents a variable in the computation graph - or more generally it
|
"""A Net represents a scalar type in the computation graph - or more generally it
|
||||||
connects Nodes together.
|
connects Nodes together.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
|
@ -86,19 +86,19 @@ class Net:
|
||||||
return self.source.node_hash
|
return self.source.node_hash
|
||||||
|
|
||||||
|
|
||||||
class variable(Generic[TNum], Net):
|
class value(Generic[TNum], Net):
|
||||||
"""A "variable" represents a typed variable. It supports arithmetic and
|
"""A "value" represents a typed scalar variable. It supports arithmetic and
|
||||||
comparison operations.
|
comparison operations.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
dtype (str): Data type of this variable.
|
dtype (str): Data type of this value.
|
||||||
"""
|
"""
|
||||||
def __init__(self, source: TNum | Node, dtype: str | None = None):
|
def __init__(self, source: TNum | Node, dtype: str | None = None):
|
||||||
"""Instance a variable.
|
"""Instance a value.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
source: A numeric value or Node object.
|
source: A numeric value or Node object.
|
||||||
dtype: Data type of this variable. Required if source is a Node.
|
dtype: Data type of this value. Required if source is a Node.
|
||||||
"""
|
"""
|
||||||
if isinstance(source, Node):
|
if isinstance(source, Node):
|
||||||
self.source = source
|
self.source = source
|
||||||
|
|
@ -115,67 +115,67 @@ class variable(Generic[TNum], Net):
|
||||||
self.dtype = 'int'
|
self.dtype = 'int'
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __add__(self: 'variable[TNum]', other: 'variable[TNum] | TNum') -> 'variable[TNum]': ...
|
def __add__(self: 'value[TNum]', other: 'value[TNum] | TNum') -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __add__(self: 'variable[int]', other: uniint) -> 'variable[int]': ...
|
def __add__(self: 'value[int]', other: uniint) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __add__(self, other: unifloat) -> 'variable[float]': ...
|
def __add__(self, other: unifloat) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __add__(self: 'variable[float]', other: NumLike) -> 'variable[float]': ...
|
def __add__(self: 'value[float]', other: NumLike) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __add__(self, other: TVarNumb) -> 'variable[float] | variable[int]': ...
|
def __add__(self, other: TVarNumb) -> 'value[float] | value[int]': ...
|
||||||
def __add__(self, other: TVarNumb) -> Any:
|
def __add__(self, other: TVarNumb) -> Any:
|
||||||
if not isinstance(other, variable) and other == 0:
|
if not isinstance(other, value) and other == 0:
|
||||||
return self
|
return self
|
||||||
return add_op('add', [self, other], True)
|
return add_op('add', [self, other], True)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self: 'variable[TNum]', other: TNum) -> 'variable[TNum]': ...
|
def __radd__(self: 'value[TNum]', other: TNum) -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self: 'variable[int]', other: int) -> 'variable[int]': ...
|
def __radd__(self: 'value[int]', other: int) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self, other: float) -> 'variable[float]': ...
|
def __radd__(self, other: float) -> 'value[float]': ...
|
||||||
def __radd__(self, other: NumLike) -> Any:
|
def __radd__(self, other: NumLike) -> Any:
|
||||||
return self + other
|
return self + other
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __sub__(self: 'variable[TNum]', other: 'variable[TNum] | TNum') -> 'variable[TNum]': ...
|
def __sub__(self: 'value[TNum]', other: 'value[TNum] | TNum') -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __sub__(self: 'variable[int]', other: uniint) -> 'variable[int]': ...
|
def __sub__(self: 'value[int]', other: uniint) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __sub__(self, other: unifloat) -> 'variable[float]': ...
|
def __sub__(self, other: unifloat) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __sub__(self: 'variable[float]', other: NumLike) -> 'variable[float]': ...
|
def __sub__(self: 'value[float]', other: NumLike) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __sub__(self, other: TVarNumb) -> 'variable[float] | variable[int]': ...
|
def __sub__(self, other: TVarNumb) -> 'value[float] | value[int]': ...
|
||||||
def __sub__(self, other: TVarNumb) -> Any:
|
def __sub__(self, other: TVarNumb) -> Any:
|
||||||
if isinstance(other, int | float) and other == 0:
|
if isinstance(other, int | float) and other == 0:
|
||||||
return self
|
return self
|
||||||
return add_op('sub', [self, other])
|
return add_op('sub', [self, other])
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self: 'variable[TNum]', other: TNum) -> 'variable[TNum]': ...
|
def __rsub__(self: 'value[TNum]', other: TNum) -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self: 'variable[int]', other: int) -> 'variable[int]': ...
|
def __rsub__(self: 'value[int]', other: int) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self, other: float) -> 'variable[float]': ...
|
def __rsub__(self, other: float) -> 'value[float]': ...
|
||||||
def __rsub__(self, other: NumLike) -> Any:
|
def __rsub__(self, other: NumLike) -> Any:
|
||||||
return add_op('sub', [other, self])
|
return add_op('sub', [other, self])
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __mul__(self: 'variable[TNum]', other: 'variable[TNum] | TNum') -> 'variable[TNum]': ...
|
def __mul__(self: 'value[TNum]', other: 'value[TNum] | TNum') -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mul__(self: 'variable[int]', other: uniint) -> 'variable[int]': ...
|
def __mul__(self: 'value[int]', other: uniint) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mul__(self, other: unifloat) -> 'variable[float]': ...
|
def __mul__(self, other: unifloat) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mul__(self: 'variable[float]', other: NumLike) -> 'variable[float]': ...
|
def __mul__(self: 'value[float]', other: NumLike) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mul__(self, other: TVarNumb) -> 'variable[float] | variable[int]': ...
|
def __mul__(self, other: TVarNumb) -> 'value[float] | value[int]': ...
|
||||||
def __mul__(self, other: TVarNumb) -> Any:
|
def __mul__(self, other: TVarNumb) -> Any:
|
||||||
if self.dtype == 'float' and isinstance(other, int):
|
if self.dtype == 'float' and isinstance(other, int):
|
||||||
other = float(other) # Prevent runtime conversion of consts; TODO: add this for other operations
|
other = float(other) # Prevent runtime conversion of consts; TODO: add this for other operations
|
||||||
if not isinstance(other, variable):
|
if not isinstance(other, value):
|
||||||
if other == 1:
|
if other == 1:
|
||||||
return self
|
return self
|
||||||
elif other == 0:
|
elif other == 0:
|
||||||
|
|
@ -183,112 +183,112 @@ class variable(Generic[TNum], Net):
|
||||||
return add_op('mul', [self, other], True)
|
return add_op('mul', [self, other], True)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self: 'variable[TNum]', other: TNum) -> 'variable[TNum]': ...
|
def __rmul__(self: 'value[TNum]', other: TNum) -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self: 'variable[int]', other: int) -> 'variable[int]': ...
|
def __rmul__(self: 'value[int]', other: int) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self, other: float) -> 'variable[float]': ...
|
def __rmul__(self, other: float) -> 'value[float]': ...
|
||||||
def __rmul__(self, other: NumLike) -> Any:
|
def __rmul__(self, other: NumLike) -> Any:
|
||||||
return self * other
|
return self * other
|
||||||
|
|
||||||
def __truediv__(self, other: NumLike) -> 'variable[float]':
|
def __truediv__(self, other: NumLike) -> 'value[float]':
|
||||||
return add_op('div', [self, other])
|
return add_op('div', [self, other])
|
||||||
|
|
||||||
def __rtruediv__(self, other: NumLike) -> 'variable[float]':
|
def __rtruediv__(self, other: NumLike) -> 'value[float]':
|
||||||
return add_op('div', [other, self])
|
return add_op('div', [other, self])
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __floordiv__(self: 'variable[TNum]', other: 'variable[TNum] | TNum') -> 'variable[TNum]': ...
|
def __floordiv__(self: 'value[TNum]', other: 'value[TNum] | TNum') -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __floordiv__(self: 'variable[int]', other: uniint) -> 'variable[int]': ...
|
def __floordiv__(self: 'value[int]', other: uniint) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __floordiv__(self, other: unifloat) -> 'variable[float]': ...
|
def __floordiv__(self, other: unifloat) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __floordiv__(self: 'variable[float]', other: NumLike) -> 'variable[float]': ...
|
def __floordiv__(self: 'value[float]', other: NumLike) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __floordiv__(self, other: TVarNumb) -> 'variable[float] | variable[int]': ...
|
def __floordiv__(self, other: TVarNumb) -> 'value[float] | value[int]': ...
|
||||||
def __floordiv__(self, other: TVarNumb) -> Any:
|
def __floordiv__(self, other: TVarNumb) -> Any:
|
||||||
return add_op('floordiv', [self, other])
|
return add_op('floordiv', [self, other])
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __rfloordiv__(self: 'variable[TNum]', other: TNum) -> 'variable[TNum]': ...
|
def __rfloordiv__(self: 'value[TNum]', other: TNum) -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rfloordiv__(self: 'variable[int]', other: int) -> 'variable[int]': ...
|
def __rfloordiv__(self: 'value[int]', other: int) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rfloordiv__(self, other: float) -> 'variable[float]': ...
|
def __rfloordiv__(self, other: float) -> 'value[float]': ...
|
||||||
def __rfloordiv__(self, other: NumLike) -> Any:
|
def __rfloordiv__(self, other: NumLike) -> Any:
|
||||||
return add_op('floordiv', [other, self])
|
return add_op('floordiv', [other, self])
|
||||||
|
|
||||||
def __neg__(self: TCPNum) -> TCPNum:
|
def __neg__(self: TCPNum) -> TCPNum:
|
||||||
if self.dtype == 'int':
|
if self.dtype == 'int':
|
||||||
return cast(TCPNum, add_op('sub', [variable(0), self]))
|
return cast(TCPNum, add_op('sub', [value(0), self]))
|
||||||
return cast(TCPNum, add_op('sub', [variable(0.0), self]))
|
return cast(TCPNum, add_op('sub', [value(0.0), self]))
|
||||||
|
|
||||||
def __gt__(self, other: TVarNumb) -> 'variable[int]':
|
def __gt__(self, other: TVarNumb) -> 'value[int]':
|
||||||
ret = add_op('gt', [self, other])
|
ret = add_op('gt', [self, other])
|
||||||
return variable(ret.source, dtype='bool')
|
return value(ret.source, dtype='bool')
|
||||||
|
|
||||||
def __lt__(self, other: TVarNumb) -> 'variable[int]':
|
def __lt__(self, other: TVarNumb) -> 'value[int]':
|
||||||
ret = add_op('gt', [other, self])
|
ret = add_op('gt', [other, self])
|
||||||
return variable(ret.source, dtype='bool')
|
return value(ret.source, dtype='bool')
|
||||||
|
|
||||||
def __ge__(self, other: TVarNumb) -> 'variable[int]':
|
def __ge__(self, other: TVarNumb) -> 'value[int]':
|
||||||
ret = add_op('ge', [self, other])
|
ret = add_op('ge', [self, other])
|
||||||
return variable(ret.source, dtype='bool')
|
return value(ret.source, dtype='bool')
|
||||||
|
|
||||||
def __le__(self, other: TVarNumb) -> 'variable[int]':
|
def __le__(self, other: TVarNumb) -> 'value[int]':
|
||||||
ret = add_op('ge', [other, self])
|
ret = add_op('ge', [other, self])
|
||||||
return variable(ret.source, dtype='bool')
|
return value(ret.source, dtype='bool')
|
||||||
|
|
||||||
def __eq__(self, other: TVarNumb) -> 'variable[int]': # type: ignore
|
def __eq__(self, other: TVarNumb) -> 'value[int]': # type: ignore
|
||||||
ret = add_op('eq', [self, other], True)
|
ret = add_op('eq', [self, other], True)
|
||||||
return variable(ret.source, dtype='bool')
|
return value(ret.source, dtype='bool')
|
||||||
|
|
||||||
def __ne__(self, other: TVarNumb) -> 'variable[int]': # type: ignore
|
def __ne__(self, other: TVarNumb) -> 'value[int]': # type: ignore
|
||||||
ret = add_op('ne', [self, other], True)
|
ret = add_op('ne', [self, other], True)
|
||||||
return variable(ret.source, dtype='bool')
|
return value(ret.source, dtype='bool')
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __mod__(self: 'variable[TNum]', other: 'variable[TNum] | TNum') -> 'variable[TNum]': ...
|
def __mod__(self: 'value[TNum]', other: 'value[TNum] | TNum') -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mod__(self: 'variable[int]', other: uniint) -> 'variable[int]': ...
|
def __mod__(self: 'value[int]', other: uniint) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mod__(self, other: unifloat) -> 'variable[float]': ...
|
def __mod__(self, other: unifloat) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mod__(self: 'variable[float]', other: NumLike) -> 'variable[float]': ...
|
def __mod__(self: 'value[float]', other: NumLike) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __mod__(self, other: TVarNumb) -> 'variable[float] | variable[int]': ...
|
def __mod__(self, other: TVarNumb) -> 'value[float] | value[int]': ...
|
||||||
def __mod__(self, other: TVarNumb) -> Any:
|
def __mod__(self, other: TVarNumb) -> Any:
|
||||||
return add_op('mod', [self, other])
|
return add_op('mod', [self, other])
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __rmod__(self: 'variable[TNum]', other: TNum) -> 'variable[TNum]': ...
|
def __rmod__(self: 'value[TNum]', other: TNum) -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rmod__(self: 'variable[int]', other: int) -> 'variable[int]': ...
|
def __rmod__(self: 'value[int]', other: int) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rmod__(self, other: float) -> 'variable[float]': ...
|
def __rmod__(self, other: float) -> 'value[float]': ...
|
||||||
def __rmod__(self, other: NumLike) -> Any:
|
def __rmod__(self, other: NumLike) -> Any:
|
||||||
return add_op('mod', [other, self])
|
return add_op('mod', [other, self])
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __pow__(self: 'variable[TNum]', other: 'variable[TNum] | TNum') -> 'variable[TNum]': ...
|
def __pow__(self: 'value[TNum]', other: 'value[TNum] | TNum') -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __pow__(self: 'variable[int]', other: uniint) -> 'variable[int]': ...
|
def __pow__(self: 'value[int]', other: uniint) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __pow__(self, other: unifloat) -> 'variable[float]': ...
|
def __pow__(self, other: unifloat) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __pow__(self: 'variable[float]', other: NumLike) -> 'variable[float]': ...
|
def __pow__(self: 'value[float]', other: NumLike) -> 'value[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __pow__(self, other: TVarNumb) -> 'variable[float] | variable[int]': ...
|
def __pow__(self, other: TVarNumb) -> 'value[float] | value[int]': ...
|
||||||
def __pow__(self, other: TVarNumb) -> Any:
|
def __pow__(self, other: TVarNumb) -> Any:
|
||||||
return cp.pow(self, other)
|
return cp.pow(self, other)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __rpow__(self: 'variable[TNum]', other: TNum) -> 'variable[TNum]': ...
|
def __rpow__(self: 'value[TNum]', other: TNum) -> 'value[TNum]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rpow__(self: 'variable[int]', other: int) -> 'variable[int]': ...
|
def __rpow__(self: 'value[int]', other: int) -> 'value[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rpow__(self, other: float) -> 'variable[float]': ...
|
def __rpow__(self, other: float) -> 'value[float]': ...
|
||||||
def __rpow__(self, other: NumLike) -> Any:
|
def __rpow__(self, other: NumLike) -> Any:
|
||||||
return cp.pow(other, self)
|
return cp.pow(other, self)
|
||||||
|
|
||||||
|
|
@ -296,34 +296,34 @@ class variable(Generic[TNum], Net):
|
||||||
return super().__hash__()
|
return super().__hash__()
|
||||||
|
|
||||||
# Bitwise and shift operations for cp[int]
|
# Bitwise and shift operations for cp[int]
|
||||||
def __lshift__(self, other: uniint) -> 'variable[int]':
|
def __lshift__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('lshift', [self, other])
|
return add_op('lshift', [self, other])
|
||||||
|
|
||||||
def __rlshift__(self, other: uniint) -> 'variable[int]':
|
def __rlshift__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('lshift', [other, self])
|
return add_op('lshift', [other, self])
|
||||||
|
|
||||||
def __rshift__(self, other: uniint) -> 'variable[int]':
|
def __rshift__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('rshift', [self, other])
|
return add_op('rshift', [self, other])
|
||||||
|
|
||||||
def __rrshift__(self, other: uniint) -> 'variable[int]':
|
def __rrshift__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('rshift', [other, self])
|
return add_op('rshift', [other, self])
|
||||||
|
|
||||||
def __and__(self, other: uniint) -> 'variable[int]':
|
def __and__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('bwand', [self, other], True)
|
return add_op('bwand', [self, other], True)
|
||||||
|
|
||||||
def __rand__(self, other: uniint) -> 'variable[int]':
|
def __rand__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('bwand', [other, self], True)
|
return add_op('bwand', [other, self], True)
|
||||||
|
|
||||||
def __or__(self, other: uniint) -> 'variable[int]':
|
def __or__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('bwor', [self, other], True)
|
return add_op('bwor', [self, other], True)
|
||||||
|
|
||||||
def __ror__(self, other: uniint) -> 'variable[int]':
|
def __ror__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('bwor', [other, self], True)
|
return add_op('bwor', [other, self], True)
|
||||||
|
|
||||||
def __xor__(self, other: uniint) -> 'variable[int]':
|
def __xor__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('bwxor', [self, other], True)
|
return add_op('bwxor', [self, other], True)
|
||||||
|
|
||||||
def __rxor__(self, other: uniint) -> 'variable[int]':
|
def __rxor__(self, other: uniint) -> 'value[int]':
|
||||||
return add_op('bwxor', [other, self], True)
|
return add_op('bwxor', [other, self], True)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -356,30 +356,30 @@ class Op(Node):
|
||||||
self.node_hash = self.get_node_hash(commutative)
|
self.node_hash = self.get_node_hash(commutative)
|
||||||
|
|
||||||
|
|
||||||
def net_from_value(value: Any) -> variable[Any]:
|
def net_from_value(val: Any) -> value[Any]:
|
||||||
vi = CPConstant(value)
|
vi = CPConstant(val)
|
||||||
return variable(vi, vi.dtype)
|
return value(vi, vi.dtype)
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def iif(expression: variable[Any], true_result: uniint, false_result: uniint) -> variable[int]: ... # pyright: ignore[reportOverlappingOverload]
|
def iif(expression: value[Any], true_result: uniint, false_result: uniint) -> value[int]: ... # pyright: ignore[reportOverlappingOverload]
|
||||||
@overload
|
@overload
|
||||||
def iif(expression: variable[Any], true_result: unifloat, false_result: unifloat) -> variable[float]: ...
|
def iif(expression: value[Any], true_result: unifloat, false_result: unifloat) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def iif(expression: float | int, true_result: TNum, false_result: TNum) -> TNum: ...
|
def iif(expression: float | int, true_result: TNum, false_result: TNum) -> TNum: ...
|
||||||
@overload
|
@overload
|
||||||
def iif(expression: float | int, true_result: TNum | variable[TNum], false_result: variable[TNum]) -> variable[TNum]: ...
|
def iif(expression: float | int, true_result: TNum | value[TNum], false_result: value[TNum]) -> value[TNum]: ...
|
||||||
@overload
|
@overload
|
||||||
def iif(expression: float | int, true_result: variable[TNum], false_result: TNum | variable[TNum]) -> variable[TNum]: ...
|
def iif(expression: float | int, true_result: value[TNum], false_result: TNum | value[TNum]) -> value[TNum]: ...
|
||||||
@overload
|
@overload
|
||||||
def iif(expression: float | int | variable[Any], true_result: TNum | variable[TNum], false_result: TNum | variable[TNum]) -> variable[TNum] | TNum: ...
|
def iif(expression: float | int | value[Any], true_result: TNum | value[TNum], false_result: TNum | value[TNum]) -> value[TNum] | TNum: ...
|
||||||
def iif(expression: Any, true_result: Any, false_result: Any) -> Any:
|
def iif(expression: Any, true_result: Any, false_result: Any) -> Any:
|
||||||
allowed_type = (variable, int, float)
|
allowed_type = (value, int, float)
|
||||||
assert isinstance(true_result, allowed_type) and isinstance(false_result, allowed_type), "Result type not supported"
|
assert isinstance(true_result, allowed_type) and isinstance(false_result, allowed_type), "Result type not supported"
|
||||||
return (expression != 0) * true_result + (expression == 0) * false_result
|
return (expression != 0) * true_result + (expression == 0) * false_result
|
||||||
|
|
||||||
|
|
||||||
def add_op(op: str, args: list[variable[Any] | int | float], commutative: bool = False) -> variable[Any]:
|
def add_op(op: str, args: list[value[Any] | int | float], commutative: bool = False) -> value[Any]:
|
||||||
arg_nets = [a if isinstance(a, Net) else net_from_value(a) for a in args]
|
arg_nets = [a if isinstance(a, Net) else net_from_value(a) for a in args]
|
||||||
|
|
||||||
if commutative:
|
if commutative:
|
||||||
|
|
@ -393,9 +393,9 @@ def add_op(op: str, args: list[variable[Any] | int | float], commutative: bool =
|
||||||
result_type = generic_sdb.stencil_definitions[typed_op].split('_')[0]
|
result_type = generic_sdb.stencil_definitions[typed_op].split('_')[0]
|
||||||
|
|
||||||
if result_type == 'float':
|
if result_type == 'float':
|
||||||
return variable[float](Op(typed_op, arg_nets, commutative), result_type)
|
return value[float](Op(typed_op, arg_nets, commutative), result_type)
|
||||||
else:
|
else:
|
||||||
return variable[int](Op(typed_op, arg_nets, commutative), result_type)
|
return value[int](Op(typed_op, arg_nets, commutative), result_type)
|
||||||
|
|
||||||
|
|
||||||
def _get_data_and_dtype(value: Any) -> tuple[str, float | int]:
|
def _get_data_and_dtype(value: Any) -> tuple[str, float | int]:
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
from . import vector
|
from . import vector
|
||||||
from ._vectors import VecNumLike
|
from ._vectors import VecNumLike
|
||||||
from . import variable, NumLike
|
from . import value, NumLike
|
||||||
from typing import TypeVar, Any, overload, Callable
|
from typing import TypeVar, Any, overload, Callable
|
||||||
from ._basic_types import add_op, unifloat
|
from ._basic_types import add_op, unifloat
|
||||||
import math
|
import math
|
||||||
|
|
||||||
T = TypeVar("T", int, float, variable[int], variable[float])
|
T = TypeVar("T", int, float, value[int], value[float])
|
||||||
U = TypeVar("U", int, float)
|
U = TypeVar("U", int, float)
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def exp(x: float | int) -> float: ...
|
def exp(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def exp(x: variable[Any]) -> variable[float]: ...
|
def exp(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def exp(x: vector[Any]) -> vector[float]: ...
|
def exp(x: vector[Any]) -> vector[float]: ...
|
||||||
def exp(x: Any) -> Any:
|
def exp(x: Any) -> Any:
|
||||||
|
|
@ -24,7 +24,7 @@ def exp(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
result of e**x
|
result of e**x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('exp', [x])
|
return add_op('exp', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(exp)
|
return x.map(exp)
|
||||||
|
|
@ -34,7 +34,7 @@ def exp(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def log(x: float | int) -> float: ...
|
def log(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def log(x: variable[Any]) -> variable[float]: ...
|
def log(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def log(x: vector[Any]) -> vector[float]: ...
|
def log(x: vector[Any]) -> vector[float]: ...
|
||||||
def log(x: Any) -> Any:
|
def log(x: Any) -> Any:
|
||||||
|
|
@ -46,7 +46,7 @@ def log(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
result of ln(x)
|
result of ln(x)
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('log', [x])
|
return add_op('log', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(log)
|
return x.map(log)
|
||||||
|
|
@ -56,9 +56,9 @@ def log(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def pow(x: float | int, y: float | int) -> float: ...
|
def pow(x: float | int, y: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def pow(x: variable[Any], y: NumLike) -> variable[float]: ...
|
def pow(x: value[Any], y: NumLike) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def pow(x: NumLike, y: variable[Any]) -> variable[float]: ...
|
def pow(x: NumLike, y: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def pow(x: vector[Any], y: Any) -> vector[float]: ...
|
def pow(x: vector[Any], y: Any) -> vector[float]: ...
|
||||||
def pow(x: VecNumLike, y: VecNumLike) -> Any:
|
def pow(x: VecNumLike, y: VecNumLike) -> Any:
|
||||||
|
|
@ -81,7 +81,7 @@ def pow(x: VecNumLike, y: VecNumLike) -> Any:
|
||||||
return m
|
return m
|
||||||
if y == -1:
|
if y == -1:
|
||||||
return 1 / x
|
return 1 / x
|
||||||
if isinstance(x, variable) or isinstance(y, variable):
|
if isinstance(x, value) or isinstance(y, value):
|
||||||
return add_op('pow', [x, y])
|
return add_op('pow', [x, y])
|
||||||
else:
|
else:
|
||||||
return float(x ** y)
|
return float(x ** y)
|
||||||
|
|
@ -90,7 +90,7 @@ def pow(x: VecNumLike, y: VecNumLike) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def sqrt(x: float | int) -> float: ...
|
def sqrt(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def sqrt(x: variable[Any]) -> variable[float]: ...
|
def sqrt(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def sqrt(x: vector[Any]) -> vector[float]: ...
|
def sqrt(x: vector[Any]) -> vector[float]: ...
|
||||||
def sqrt(x: Any) -> Any:
|
def sqrt(x: Any) -> Any:
|
||||||
|
|
@ -102,7 +102,7 @@ def sqrt(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
Square root of x
|
Square root of x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('sqrt', [x])
|
return add_op('sqrt', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(sqrt)
|
return x.map(sqrt)
|
||||||
|
|
@ -112,7 +112,7 @@ def sqrt(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def sin(x: float | int) -> float: ...
|
def sin(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def sin(x: variable[Any]) -> variable[float]: ...
|
def sin(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def sin(x: vector[Any]) -> vector[float]: ...
|
def sin(x: vector[Any]) -> vector[float]: ...
|
||||||
def sin(x: Any) -> Any:
|
def sin(x: Any) -> Any:
|
||||||
|
|
@ -124,7 +124,7 @@ def sin(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
Square root of x
|
Square root of x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('sin', [x])
|
return add_op('sin', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(sin)
|
return x.map(sin)
|
||||||
|
|
@ -134,7 +134,7 @@ def sin(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def cos(x: float | int) -> float: ...
|
def cos(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def cos(x: variable[Any]) -> variable[float]: ...
|
def cos(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def cos(x: vector[Any]) -> vector[float]: ...
|
def cos(x: vector[Any]) -> vector[float]: ...
|
||||||
def cos(x: Any) -> Any:
|
def cos(x: Any) -> Any:
|
||||||
|
|
@ -146,7 +146,7 @@ def cos(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
Cosine of x
|
Cosine of x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('cos', [x])
|
return add_op('cos', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(cos)
|
return x.map(cos)
|
||||||
|
|
@ -156,7 +156,7 @@ def cos(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def tan(x: float | int) -> float: ...
|
def tan(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def tan(x: variable[Any]) -> variable[float]: ...
|
def tan(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def tan(x: vector[Any]) -> vector[float]: ...
|
def tan(x: vector[Any]) -> vector[float]: ...
|
||||||
def tan(x: Any) -> Any:
|
def tan(x: Any) -> Any:
|
||||||
|
|
@ -168,7 +168,7 @@ def tan(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
Tangent of x
|
Tangent of x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('tan', [x])
|
return add_op('tan', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
#return x.map(tan)
|
#return x.map(tan)
|
||||||
|
|
@ -179,7 +179,7 @@ def tan(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def atan(x: float | int) -> float: ...
|
def atan(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def atan(x: variable[Any]) -> variable[float]: ...
|
def atan(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def atan(x: vector[Any]) -> vector[float]: ...
|
def atan(x: vector[Any]) -> vector[float]: ...
|
||||||
def atan(x: Any) -> Any:
|
def atan(x: Any) -> Any:
|
||||||
|
|
@ -191,7 +191,7 @@ def atan(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
Inverse tangent of x
|
Inverse tangent of x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('atan', [x])
|
return add_op('atan', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(atan)
|
return x.map(atan)
|
||||||
|
|
@ -201,9 +201,9 @@ def atan(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def atan2(x: float | int, y: float | int) -> float: ...
|
def atan2(x: float | int, y: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def atan2(x: variable[Any], y: NumLike) -> variable[float]: ...
|
def atan2(x: value[Any], y: NumLike) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def atan2(x: NumLike, y: variable[Any]) -> variable[float]: ...
|
def atan2(x: NumLike, y: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def atan2(x: vector[float], y: VecNumLike) -> vector[float]: ...
|
def atan2(x: vector[float], y: VecNumLike) -> vector[float]: ...
|
||||||
@overload
|
@overload
|
||||||
|
|
@ -220,7 +220,7 @@ def atan2(x: VecNumLike, y: VecNumLike) -> Any:
|
||||||
"""
|
"""
|
||||||
if isinstance(x, vector) or isinstance(y, vector):
|
if isinstance(x, vector) or isinstance(y, vector):
|
||||||
return _map2(x, y, atan2)
|
return _map2(x, y, atan2)
|
||||||
if isinstance(x, variable) or isinstance(y, variable):
|
if isinstance(x, value) or isinstance(y, value):
|
||||||
return add_op('atan2', [x, y])
|
return add_op('atan2', [x, y])
|
||||||
return math.atan2(x, y)
|
return math.atan2(x, y)
|
||||||
|
|
||||||
|
|
@ -228,7 +228,7 @@ def atan2(x: VecNumLike, y: VecNumLike) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def asin(x: float | int) -> float: ...
|
def asin(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def asin(x: variable[Any]) -> variable[float]: ...
|
def asin(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def asin(x: vector[Any]) -> vector[float]: ...
|
def asin(x: vector[Any]) -> vector[float]: ...
|
||||||
def asin(x: Any) -> Any:
|
def asin(x: Any) -> Any:
|
||||||
|
|
@ -240,7 +240,7 @@ def asin(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
Inverse sine of x
|
Inverse sine of x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('asin', [x])
|
return add_op('asin', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(asin)
|
return x.map(asin)
|
||||||
|
|
@ -250,7 +250,7 @@ def asin(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def acos(x: float | int) -> float: ...
|
def acos(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def acos(x: variable[Any]) -> variable[float]: ...
|
def acos(x: value[Any]) -> value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def acos(x: vector[Any]) -> vector[float]: ...
|
def acos(x: vector[Any]) -> vector[float]: ...
|
||||||
def acos(x: Any) -> Any:
|
def acos(x: Any) -> Any:
|
||||||
|
|
@ -262,7 +262,7 @@ def acos(x: Any) -> Any:
|
||||||
Returns:
|
Returns:
|
||||||
Inverse cosine of x
|
Inverse cosine of x
|
||||||
"""
|
"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('acos', [x])
|
return add_op('acos', [x])
|
||||||
if isinstance(x, vector):
|
if isinstance(x, vector):
|
||||||
return x.map(acos)
|
return x.map(acos)
|
||||||
|
|
@ -272,10 +272,10 @@ def acos(x: Any) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def get_42(x: float | int) -> float: ...
|
def get_42(x: float | int) -> float: ...
|
||||||
@overload
|
@overload
|
||||||
def get_42(x: variable[Any]) -> variable[float]: ...
|
def get_42(x: value[Any]) -> value[float]: ...
|
||||||
def get_42(x: NumLike) -> variable[float] | float:
|
def get_42(x: NumLike) -> value[float] | float:
|
||||||
"""Returns the variable representing the constant 42"""
|
"""Returns the value representing the constant 42"""
|
||||||
if isinstance(x, variable):
|
if isinstance(x, value):
|
||||||
return add_op('get_42', [x, x])
|
return add_op('get_42', [x, x])
|
||||||
return float((int(x) * 3.0 + 42.0) * 5.0 + 21.0)
|
return float((int(x) * 3.0 + 42.0) * 5.0 + 21.0)
|
||||||
|
|
||||||
|
|
@ -284,10 +284,10 @@ def get_42(x: NumLike) -> variable[float] | float:
|
||||||
@overload
|
@overload
|
||||||
def abs(x: U) -> U: ...
|
def abs(x: U) -> U: ...
|
||||||
@overload
|
@overload
|
||||||
def abs(x: variable[U]) -> variable[U]: ...
|
def abs(x: value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def abs(x: vector[U]) -> vector[U]: ...
|
def abs(x: vector[U]) -> vector[U]: ...
|
||||||
def abs(x: U | variable[U] | vector[U]) -> Any:
|
def abs(x: U | value[U] | vector[U]) -> Any:
|
||||||
"""Absolute value function
|
"""Absolute value function
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
@ -304,10 +304,10 @@ def abs(x: U | variable[U] | vector[U]) -> Any:
|
||||||
@overload
|
@overload
|
||||||
def sign(x: U) -> U: ...
|
def sign(x: U) -> U: ...
|
||||||
@overload
|
@overload
|
||||||
def sign(x: variable[U]) -> variable[U]: ...
|
def sign(x: value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def sign(x: vector[U]) -> vector[U]: ...
|
def sign(x: vector[U]) -> vector[U]: ...
|
||||||
def sign(x: U | variable[U] | vector[U]) -> Any:
|
def sign(x: U | value[U] | vector[U]) -> Any:
|
||||||
"""Return 1 for positive numbers and -1 for negative numbers.
|
"""Return 1 for positive numbers and -1 for negative numbers.
|
||||||
For an input of 0 the return value is 0.
|
For an input of 0 the return value is 0.
|
||||||
|
|
||||||
|
|
@ -322,16 +322,16 @@ def sign(x: U | variable[U] | vector[U]) -> Any:
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def clamp(x: variable[U], min_value: U | variable[U], max_value: U | variable[U]) -> variable[U]: ...
|
def clamp(x: value[U], min_value: U | value[U], max_value: U | value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def clamp(x: U | variable[U], min_value: variable[U], max_value: U | variable[U]) -> variable[U]: ...
|
def clamp(x: U | value[U], min_value: value[U], max_value: U | value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def clamp(x: U | variable[U], min_value: U | variable[U], max_value: variable[U]) -> variable[U]: ...
|
def clamp(x: U | value[U], min_value: U | value[U], max_value: value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def clamp(x: U, min_value: U, max_value: U) -> U: ...
|
def clamp(x: U, min_value: U, max_value: U) -> U: ...
|
||||||
@overload
|
@overload
|
||||||
def clamp(x: vector[U], min_value: 'U | variable[U]', max_value: 'U | variable[U]') -> vector[U]: ...
|
def clamp(x: vector[U], min_value: 'U | value[U]', max_value: 'U | value[U]') -> vector[U]: ...
|
||||||
def clamp(x: U | variable[U] | vector[U], min_value: U | variable[U], max_value: U | variable[U]) -> Any:
|
def clamp(x: U | value[U] | vector[U], min_value: U | value[U], max_value: U | value[U]) -> Any:
|
||||||
"""Clamp function to limit a value between a minimum and maximum.
|
"""Clamp function to limit a value between a minimum and maximum.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
@ -351,12 +351,12 @@ def clamp(x: U | variable[U] | vector[U], min_value: U | variable[U], max_value:
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def min(x: variable[U], y: U | variable[U]) -> variable[U]: ...
|
def min(x: value[U], y: U | value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def min(x: U | variable[U], y: variable[U]) -> variable[U]: ...
|
def min(x: U | value[U], y: value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def min(x: U, y: U) -> U: ...
|
def min(x: U, y: U) -> U: ...
|
||||||
def min(x: U | variable[U], y: U | variable[U]) -> Any:
|
def min(x: U | value[U], y: U | value[U]) -> Any:
|
||||||
"""Minimum function to get the smaller of two values.
|
"""Minimum function to get the smaller of two values.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
@ -370,12 +370,12 @@ def min(x: U | variable[U], y: U | variable[U]) -> Any:
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def max(x: variable[U], y: U | variable[U]) -> variable[U]: ...
|
def max(x: value[U], y: U | value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def max(x: U | variable[U], y: variable[U]) -> variable[U]: ...
|
def max(x: U | value[U], y: value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def max(x: U, y: U) -> U: ...
|
def max(x: U, y: U) -> U: ...
|
||||||
def max(x: U | variable[U], y: U | variable[U]) -> Any:
|
def max(x: U | value[U], y: U | value[U]) -> Any:
|
||||||
"""Maximum function to get the larger of two values.
|
"""Maximum function to get the larger of two values.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
@ -389,16 +389,16 @@ def max(x: U | variable[U], y: U | variable[U]) -> Any:
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def lerp(v1: variable[U], v2: U | variable[U], t: unifloat) -> variable[U]: ...
|
def lerp(v1: value[U], v2: U | value[U], t: unifloat) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def lerp(v1: U | variable[U], v2: variable[U], t: unifloat) -> variable[U]: ...
|
def lerp(v1: U | value[U], v2: value[U], t: unifloat) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def lerp(v1: U | variable[U], v2: U | variable[U], t: variable[float]) -> variable[U]: ...
|
def lerp(v1: U | value[U], v2: U | value[U], t: value[float]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def lerp(v1: U, v2: U, t: float) -> U: ...
|
def lerp(v1: U, v2: U, t: float) -> U: ...
|
||||||
@overload
|
@overload
|
||||||
def lerp(v1: vector[U], v2: vector[U], t: unifloat) -> vector[U]: ...
|
def lerp(v1: vector[U], v2: vector[U], t: unifloat) -> vector[U]: ...
|
||||||
def lerp(v1: U | variable[U] | vector[U], v2: U | variable[U] | vector[U], t: unifloat) -> Any:
|
def lerp(v1: U | value[U] | vector[U], v2: U | value[U] | vector[U], t: unifloat) -> Any:
|
||||||
"""Linearly interpolate between two values or vectors v1 and v2 by a factor t."""
|
"""Linearly interpolate between two values or vectors v1 and v2 by a factor t."""
|
||||||
if isinstance(v1, vector) or isinstance(v2, vector):
|
if isinstance(v1, vector) or isinstance(v2, vector):
|
||||||
assert isinstance(v1, vector) and isinstance(v2, vector), "None or both v1 and v2 must be vectors."
|
assert isinstance(v1, vector) and isinstance(v2, vector), "None or both v1 and v2 must be vectors."
|
||||||
|
|
@ -410,16 +410,16 @@ def lerp(v1: U | variable[U] | vector[U], v2: U | variable[U] | vector[U], t: u
|
||||||
@overload
|
@overload
|
||||||
def relu(x: U) -> U: ...
|
def relu(x: U) -> U: ...
|
||||||
@overload
|
@overload
|
||||||
def relu(x: variable[U]) -> variable[U]: ...
|
def relu(x: value[U]) -> value[U]: ...
|
||||||
@overload
|
@overload
|
||||||
def relu(x: vector[U]) -> vector[U]: ...
|
def relu(x: vector[U]) -> vector[U]: ...
|
||||||
def relu(x: U | variable[U] | vector[U]) -> Any:
|
def relu(x: U | value[U] | vector[U]) -> Any:
|
||||||
"""Returns x for x > 0 and otherwise 0."""
|
"""Returns x for x > 0 and otherwise 0."""
|
||||||
ret = (x > 0) * x
|
ret = (x > 0) * x
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def _map2(self: VecNumLike, other: VecNumLike, func: Callable[[Any, Any], variable[U] | U]) -> vector[U]:
|
def _map2(self: VecNumLike, other: VecNumLike, func: Callable[[Any, Any], value[U] | U]) -> vector[U]:
|
||||||
"""Applies a function to each element of the vector and a second vector or scalar."""
|
"""Applies a function to each element of the vector and a second vector or scalar."""
|
||||||
if isinstance(self, vector) and isinstance(other, vector):
|
if isinstance(self, vector) and isinstance(other, vector):
|
||||||
return vector(func(x, y) for x, y in zip(self.values, other.values))
|
return vector(func(x, y) for x, y in zip(self.values, other.values))
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
from . import variable
|
from . import value
|
||||||
from ._vectors import vector
|
from ._vectors import vector
|
||||||
from ._mixed import mixed_sum
|
from ._mixed import mixed_sum
|
||||||
from typing import TypeVar, Iterable, Any, overload, TypeAlias, Callable, Iterator, Generic
|
from typing import TypeVar, Iterable, Any, overload, TypeAlias, Callable, Iterator, Generic
|
||||||
from ._helper_types import TNum
|
from ._helper_types import TNum
|
||||||
|
|
||||||
MatNumLike: TypeAlias = 'matrix[int] | matrix[float] | variable[int] | variable[float] | int | float'
|
MatNumLike: TypeAlias = 'matrix[int] | matrix[float] | value[int] | value[float] | int | float'
|
||||||
MatIntLike: TypeAlias = 'matrix[int] | variable[int] | int'
|
MatIntLike: TypeAlias = 'matrix[int] | value[int] | int'
|
||||||
MatFloatLike: TypeAlias = 'matrix[float] | variable[float] | float'
|
MatFloatLike: TypeAlias = 'matrix[float] | value[float] | float'
|
||||||
U = TypeVar("U", int, float)
|
U = TypeVar("U", int, float)
|
||||||
|
|
||||||
|
|
||||||
class matrix(Generic[TNum]):
|
class matrix(Generic[TNum]):
|
||||||
"""Mathematical matrix class supporting basic operations and interactions with variables.
|
"""Mathematical matrix class supporting basic operations and interactions with values.
|
||||||
"""
|
"""
|
||||||
def __init__(self, values: Iterable[Iterable[TNum | variable[TNum]]] | vector[TNum]):
|
def __init__(self, values: Iterable[Iterable[TNum | value[TNum]]] | vector[TNum]):
|
||||||
"""Create a matrix with given values and variables.
|
"""Create a matrix with given values.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
values: iterable of iterable of constant values and variables
|
values: iterable of iterable of constant values
|
||||||
"""
|
"""
|
||||||
if isinstance(values, vector):
|
if isinstance(values, vector):
|
||||||
rows = [values.values]
|
rows = [values.values]
|
||||||
|
|
@ -27,7 +27,7 @@ class matrix(Generic[TNum]):
|
||||||
if rows:
|
if rows:
|
||||||
row_len = len(rows[0])
|
row_len = len(rows[0])
|
||||||
assert all(len(row) == row_len for row in rows), "All rows must have the same length"
|
assert all(len(row) == row_len for row in rows), "All rows must have the same length"
|
||||||
self.values: tuple[tuple[variable[TNum] | TNum, ...], ...] = tuple(rows)
|
self.values: tuple[tuple[value[TNum] | TNum, ...], ...] = tuple(rows)
|
||||||
self.rows = len(self.values)
|
self.rows = len(self.values)
|
||||||
self.cols = len(self.values[0]) if self.values else 0
|
self.cols = len(self.values[0]) if self.values else 0
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ class matrix(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, key: int) -> vector[TNum]: ...
|
def __getitem__(self, key: int) -> vector[TNum]: ...
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, key: tuple[int, int]) -> variable[TNum] | TNum: ...
|
def __getitem__(self, key: tuple[int, int]) -> value[TNum] | TNum: ...
|
||||||
def __getitem__(self, key: int | tuple[int, int]) -> Any:
|
def __getitem__(self, key: int | tuple[int, int]) -> Any:
|
||||||
"""Get a row as a vector or a specific element.
|
"""Get a row as a vector or a specific element.
|
||||||
Args:
|
Args:
|
||||||
|
|
@ -56,7 +56,7 @@ class matrix(Generic[TNum]):
|
||||||
else:
|
else:
|
||||||
return vector(self.values[key])
|
return vector(self.values[key])
|
||||||
|
|
||||||
def __iter__(self) -> Iterator[tuple[variable[TNum] | TNum, ...]]:
|
def __iter__(self) -> Iterator[tuple[value[TNum] | TNum, ...]]:
|
||||||
return iter(self.values)
|
return iter(self.values)
|
||||||
|
|
||||||
def __neg__(self) -> 'matrix[TNum]':
|
def __neg__(self) -> 'matrix[TNum]':
|
||||||
|
|
@ -86,7 +86,7 @@ class matrix(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self: 'matrix[float]', other: MatNumLike) -> 'matrix[float]': ...
|
def __radd__(self: 'matrix[float]', other: MatNumLike) -> 'matrix[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self: 'matrix[int]', other: variable[int] | int) -> 'matrix[int]': ...
|
def __radd__(self: 'matrix[int]', other: value[int] | int) -> 'matrix[int]': ...
|
||||||
def __radd__(self, other: Any) -> Any:
|
def __radd__(self, other: Any) -> Any:
|
||||||
return self + other
|
return self + other
|
||||||
|
|
||||||
|
|
@ -114,7 +114,7 @@ class matrix(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self: 'matrix[float]', other: MatNumLike) -> 'matrix[float]': ...
|
def __rsub__(self: 'matrix[float]', other: MatNumLike) -> 'matrix[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self: 'matrix[int]', other: variable[int] | int) -> 'matrix[int]': ...
|
def __rsub__(self: 'matrix[int]', other: value[int] | int) -> 'matrix[int]': ...
|
||||||
def __rsub__(self, other: MatNumLike) -> Any:
|
def __rsub__(self, other: MatNumLike) -> Any:
|
||||||
if isinstance(other, matrix):
|
if isinstance(other, matrix):
|
||||||
assert self.rows == other.rows and self.cols == other.cols, \
|
assert self.rows == other.rows and self.cols == other.cols, \
|
||||||
|
|
@ -153,7 +153,7 @@ class matrix(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self: 'matrix[float]', other: MatNumLike) -> 'matrix[float]': ...
|
def __rmul__(self: 'matrix[float]', other: MatNumLike) -> 'matrix[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self: 'matrix[int]', other: variable[int] | int) -> 'matrix[int]': ...
|
def __rmul__(self: 'matrix[int]', other: value[int] | int) -> 'matrix[int]': ...
|
||||||
def __rmul__(self, other: MatNumLike) -> Any:
|
def __rmul__(self, other: MatNumLike) -> Any:
|
||||||
return self * other
|
return self * other
|
||||||
|
|
||||||
|
|
@ -199,9 +199,9 @@ class matrix(Generic[TNum]):
|
||||||
assert isinstance(other, matrix), "Cannot multiply matrix with {type(other)}"
|
assert isinstance(other, matrix), "Cannot multiply matrix with {type(other)}"
|
||||||
assert self.cols == other.rows, \
|
assert self.cols == other.rows, \
|
||||||
f"Matrix columns ({self.cols}) must match other matrix rows ({other.rows})"
|
f"Matrix columns ({self.cols}) must match other matrix rows ({other.rows})"
|
||||||
result: list[list[TNum | variable[TNum]]] = []
|
result: list[list[TNum | value[TNum]]] = []
|
||||||
for row in self.values:
|
for row in self.values:
|
||||||
new_row: list[TNum | variable[TNum]] = []
|
new_row: list[TNum | value[TNum]] = []
|
||||||
for col_idx in range(other.cols):
|
for col_idx in range(other.cols):
|
||||||
col = tuple(other.values[i][col_idx] for i in range(other.rows))
|
col = tuple(other.values[i][col_idx] for i in range(other.rows))
|
||||||
element = sum(a * b for a, b in zip(row, col))
|
element = sum(a * b for a, b in zip(row, col))
|
||||||
|
|
@ -238,27 +238,27 @@ class matrix(Generic[TNum]):
|
||||||
return vector(self.values[i][index] for i in range(self.rows))
|
return vector(self.values[i][index] for i in range(self.rows))
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def trace(self: 'matrix[TNum]') -> TNum | variable[TNum]: ...
|
def trace(self: 'matrix[TNum]') -> TNum | value[TNum]: ...
|
||||||
@overload
|
@overload
|
||||||
def trace(self: 'matrix[int]') -> int | variable[int]: ...
|
def trace(self: 'matrix[int]') -> int | value[int]: ...
|
||||||
@overload
|
@overload
|
||||||
def trace(self: 'matrix[float]') -> float | variable[float]: ...
|
def trace(self: 'matrix[float]') -> float | value[float]: ...
|
||||||
def trace(self) -> Any:
|
def trace(self) -> Any:
|
||||||
"""Calculate the trace (sum of diagonal elements)."""
|
"""Calculate the trace (sum of diagonal elements)."""
|
||||||
assert self.rows == self.cols, "Trace is only defined for square matrices"
|
assert self.rows == self.cols, "Trace is only defined for square matrices"
|
||||||
return mixed_sum(self.values[i][i] for i in range(self.rows))
|
return mixed_sum(self.values[i][i] for i in range(self.rows))
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def sum(self: 'matrix[TNum]') -> TNum | variable[TNum]: ...
|
def sum(self: 'matrix[TNum]') -> TNum | value[TNum]: ...
|
||||||
@overload
|
@overload
|
||||||
def sum(self: 'matrix[int]') -> int | variable[int]: ...
|
def sum(self: 'matrix[int]') -> int | value[int]: ...
|
||||||
@overload
|
@overload
|
||||||
def sum(self: 'matrix[float]') -> float | variable[float]: ...
|
def sum(self: 'matrix[float]') -> float | value[float]: ...
|
||||||
def sum(self) -> Any:
|
def sum(self) -> Any:
|
||||||
"""Calculate the sum of all elements."""
|
"""Calculate the sum of all elements."""
|
||||||
return mixed_sum(a for row in self.values for a in row)
|
return mixed_sum(a for row in self.values for a in row)
|
||||||
|
|
||||||
def map(self, func: Callable[[Any], variable[U] | U]) -> 'matrix[U]':
|
def map(self, func: Callable[[Any], value[U] | U]) -> 'matrix[U]':
|
||||||
"""Applies a function to each element of the matrix and returns a new matrix."""
|
"""Applies a function to each element of the matrix and returns a new matrix."""
|
||||||
return matrix(
|
return matrix(
|
||||||
tuple(func(a) for a in row)
|
tuple(func(a) for a in row)
|
||||||
|
|
@ -266,10 +266,10 @@ class matrix(Generic[TNum]):
|
||||||
)
|
)
|
||||||
|
|
||||||
def homogenize(self) -> 'matrix[TNum]':
|
def homogenize(self) -> 'matrix[TNum]':
|
||||||
"""Convert all elements to variables if any element is a variable."""
|
"""Convert all elements to copapy values if any element is a copapy value."""
|
||||||
if any(isinstance(val, variable) for row in self.values for val in row):
|
if any(isinstance(val, value) for row in self.values for val in row):
|
||||||
return matrix(
|
return matrix(
|
||||||
tuple(variable(val) if not isinstance(val, variable) else val for val in row)
|
tuple(value(val) if not isinstance(val, value) else val for val in row)
|
||||||
for row in self.values
|
for row in self.values
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,24 @@
|
||||||
|
|
||||||
from . import variable
|
from . import value
|
||||||
from typing import TypeVar, Iterable, Any, overload
|
from typing import TypeVar, Iterable, Any, overload
|
||||||
|
|
||||||
T = TypeVar("T", int, float)
|
T = TypeVar("T", int, float)
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def mixed_sum(scalars: Iterable[float | variable[float]]) -> float | variable[float]: ...
|
def mixed_sum(scalars: Iterable[float | value[float]]) -> float | value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def mixed_sum(scalars: Iterable[int | variable[int]]) -> int | variable[int]: ...
|
def mixed_sum(scalars: Iterable[int | value[int]]) -> int | value[int]: ...
|
||||||
@overload
|
@overload
|
||||||
def mixed_sum(scalars: Iterable[T | variable[T]]) -> T | variable[T]: ...
|
def mixed_sum(scalars: Iterable[T | value[T]]) -> T | value[T]: ...
|
||||||
def mixed_sum(scalars: Iterable[int | float | variable[Any]]) -> Any:
|
def mixed_sum(scalars: Iterable[int | float | value[Any]]) -> Any:
|
||||||
sl = list(scalars)
|
sl = list(scalars)
|
||||||
return sum(a for a in sl if not isinstance(a, variable)) +\
|
return sum(a for a in sl if not isinstance(a, value)) +\
|
||||||
sum(a for a in sl if isinstance(a, variable))
|
sum(a for a in sl if isinstance(a, value))
|
||||||
|
|
||||||
|
|
||||||
def mixed_homogenize(scalars: Iterable[T | variable[T]]) -> Iterable[T] | Iterable[variable[T]]:
|
def mixed_homogenize(scalars: Iterable[T | value[T]]) -> Iterable[T] | Iterable[value[T]]:
|
||||||
if any(isinstance(val, variable) for val in scalars):
|
if any(isinstance(val, value) for val in scalars):
|
||||||
return (variable(val) if not isinstance(val, variable) else val for val in scalars)
|
return (value(val) if not isinstance(val, value) else val for val in scalars)
|
||||||
else:
|
else:
|
||||||
return (val for val in scalars if not isinstance(val, variable))
|
return (val for val in scalars if not isinstance(val, value))
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from . import _binwrite as binw
|
||||||
from coparun_module import coparun, read_data_mem
|
from coparun_module import coparun, read_data_mem
|
||||||
import struct
|
import struct
|
||||||
from ._basic_types import stencil_db_from_package
|
from ._basic_types import stencil_db_from_package
|
||||||
from ._basic_types import variable, Net, Node, Write, NumLike
|
from ._basic_types import value, Net, Node, Write, NumLike
|
||||||
from ._compiler import compile_to_dag
|
from ._compiler import compile_to_dag
|
||||||
|
|
||||||
T = TypeVar("T", int, float)
|
T = TypeVar("T", int, float)
|
||||||
|
|
@ -28,16 +28,16 @@ class Target():
|
||||||
optimization: Optimization level
|
optimization: Optimization level
|
||||||
"""
|
"""
|
||||||
self.sdb = stencil_db_from_package(arch, optimization)
|
self.sdb = stencil_db_from_package(arch, optimization)
|
||||||
self._variables: dict[Net, tuple[int, int, str]] = {}
|
self._values: dict[Net, tuple[int, int, str]] = {}
|
||||||
|
|
||||||
def compile(self, *variables: int | float | variable[int] | variable[float] | Iterable[int | float | variable[int] | variable[float]]) -> None:
|
def compile(self, *values: int | float | value[int] | value[float] | Iterable[int | float | value[int] | value[float]]) -> None:
|
||||||
"""Compiles the code to compute the given variables.
|
"""Compiles the code to compute the given values.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
variables: Variables to compute
|
values: Values to compute
|
||||||
"""
|
"""
|
||||||
nodes: list[Node] = []
|
nodes: list[Node] = []
|
||||||
for s in variables:
|
for s in values:
|
||||||
if isinstance(s, Iterable):
|
if isinstance(s, Iterable):
|
||||||
for net in s:
|
for net in s:
|
||||||
if isinstance(net, Net):
|
if isinstance(net, Net):
|
||||||
|
|
@ -46,7 +46,7 @@ class Target():
|
||||||
if isinstance(s, Net):
|
if isinstance(s, Net):
|
||||||
nodes.append(Write(s))
|
nodes.append(Write(s))
|
||||||
|
|
||||||
dw, self._variables = compile_to_dag(nodes, self.sdb)
|
dw, self._values = compile_to_dag(nodes, self.sdb)
|
||||||
dw.write_com(binw.Command.END_COM)
|
dw.write_com(binw.Command.END_COM)
|
||||||
assert coparun(dw.get_data()) > 0
|
assert coparun(dw.get_data()) > 0
|
||||||
|
|
||||||
|
|
@ -59,56 +59,56 @@ class Target():
|
||||||
assert coparun(dw.get_data()) > 0
|
assert coparun(dw.get_data()) > 0
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def read_value(self, net: variable[T]) -> T: ...
|
def read_value(self, net: value[T]) -> T: ...
|
||||||
@overload
|
@overload
|
||||||
def read_value(self, net: NumLike) -> float | int | bool: ...
|
def read_value(self, net: NumLike) -> float | int | bool: ...
|
||||||
@overload
|
@overload
|
||||||
def read_value(self, net: Iterable[T | variable[T]]) -> list[T]: ...
|
def read_value(self, net: Iterable[T | value[T]]) -> list[T]: ...
|
||||||
def read_value(self, net: NumLike | variable[T] | Iterable[T | variable[T]]) -> Any:
|
def read_value(self, net: NumLike | value[T] | Iterable[T | value[T]]) -> Any:
|
||||||
"""Reads the value of a variable.
|
"""Reads the numeric value of a copapy type.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
net: Variable to read
|
net: Values to read
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Value of the variable
|
Numeric value
|
||||||
"""
|
"""
|
||||||
if isinstance(net, Iterable):
|
if isinstance(net, Iterable):
|
||||||
return [self.read_value(ni) if isinstance(ni, variable) else ni for ni in net]
|
return [self.read_value(ni) if isinstance(ni, value) else ni for ni in net]
|
||||||
|
|
||||||
if isinstance(net, float | int):
|
if isinstance(net, float | int):
|
||||||
print("Warning: value is not a copypy value")
|
print("Warning: value is not a copypy value")
|
||||||
return net
|
return net
|
||||||
|
|
||||||
assert isinstance(net, Net), "Variable must be a copapy variable object"
|
assert isinstance(net, Net), "Argument must be a copapy value"
|
||||||
assert net in self._variables, f"Variable {net} not found. It might not have been compiled for the target."
|
assert net in self._values, f"Value {net} not found. It might not have been compiled for the target."
|
||||||
addr, lengths, var_type = self._variables[net]
|
addr, lengths, var_type = self._values[net]
|
||||||
assert lengths > 0
|
assert lengths > 0
|
||||||
data = read_data_mem(addr, lengths)
|
data = read_data_mem(addr, lengths)
|
||||||
assert data is not None and len(data) == lengths, f"Failed to read variable {net}"
|
assert data is not None and len(data) == lengths, f"Failed to read value {net}"
|
||||||
en = {'little': '<', 'big': '>'}[self.sdb.byteorder]
|
en = {'little': '<', 'big': '>'}[self.sdb.byteorder]
|
||||||
if var_type == 'float':
|
if var_type == 'float':
|
||||||
if lengths == 4:
|
if lengths == 4:
|
||||||
value = struct.unpack(en + 'f', data)[0]
|
val = struct.unpack(en + 'f', data)[0]
|
||||||
elif lengths == 8:
|
elif lengths == 8:
|
||||||
value = struct.unpack(en + 'd', data)[0]
|
val = struct.unpack(en + 'd', data)[0]
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported float length: {lengths} bytes")
|
raise ValueError(f"Unsupported float length: {lengths} bytes")
|
||||||
assert isinstance(value, float)
|
assert isinstance(val, float)
|
||||||
return value
|
return val
|
||||||
elif var_type == 'int':
|
elif var_type == 'int':
|
||||||
assert lengths in (1, 2, 4, 8), f"Unsupported int length: {lengths} bytes"
|
assert lengths in (1, 2, 4, 8), f"Unsupported int length: {lengths} bytes"
|
||||||
value = int.from_bytes(data, byteorder=self.sdb.byteorder, signed=True)
|
val = int.from_bytes(data, byteorder=self.sdb.byteorder, signed=True)
|
||||||
return value
|
return val
|
||||||
elif var_type == 'bool':
|
elif var_type == 'bool':
|
||||||
assert lengths in (1, 2, 4, 8), f"Unsupported int length: {lengths} bytes"
|
assert lengths in (1, 2, 4, 8), f"Unsupported int length: {lengths} bytes"
|
||||||
value = bool.from_bytes(data, byteorder=self.sdb.byteorder, signed=True)
|
val = bool.from_bytes(data, byteorder=self.sdb.byteorder, signed=True)
|
||||||
return value
|
return val
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported variable type: {var_type}")
|
raise ValueError(f"Unsupported value type: {var_type}")
|
||||||
|
|
||||||
def read_value_remote(self, net: Net) -> None:
|
def read_value_remote(self, net: Net) -> None:
|
||||||
"""Reads the raw data of a variable by the runner."""
|
"""Reads the raw data of a value by the runner."""
|
||||||
dw = binw.data_writer(self.sdb.byteorder)
|
dw = binw.data_writer(self.sdb.byteorder)
|
||||||
add_read_command(dw, self._variables, net)
|
add_read_command(dw, self._values, net)
|
||||||
assert coparun(dw.get_data()) > 0
|
assert coparun(dw.get_data()) > 0
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
from . import variable
|
from . import value
|
||||||
from ._mixed import mixed_sum, mixed_homogenize
|
from ._mixed import mixed_sum, mixed_homogenize
|
||||||
from typing import TypeVar, Iterable, Any, overload, TypeAlias, Callable, Iterator, Generic
|
from typing import TypeVar, Iterable, Any, overload, TypeAlias, Callable, Iterator, Generic
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
from ._helper_types import TNum
|
from ._helper_types import TNum
|
||||||
|
|
||||||
#VecNumLike: TypeAlias = 'vector[int] | vector[float] | variable[int] | variable[float] | int | float | bool'
|
#VecNumLike: TypeAlias = 'vector[int] | vector[float] | value[int] | value[float] | int | float | bool'
|
||||||
VecNumLike: TypeAlias = 'vector[Any] | variable[Any] | int | float | bool'
|
VecNumLike: TypeAlias = 'vector[Any] | value[Any] | int | float | bool'
|
||||||
VecIntLike: TypeAlias = 'vector[int] | variable[int] | int'
|
VecIntLike: TypeAlias = 'vector[int] | value[int] | int'
|
||||||
VecFloatLike: TypeAlias = 'vector[float] | variable[float] | float'
|
VecFloatLike: TypeAlias = 'vector[float] | value[float] | float'
|
||||||
U = TypeVar("U", int, float)
|
U = TypeVar("U", int, float)
|
||||||
|
|
||||||
epsilon = 1e-20
|
epsilon = 1e-20
|
||||||
|
|
||||||
|
|
||||||
class vector(Generic[TNum]):
|
class vector(Generic[TNum]):
|
||||||
"""Mathematical vector class supporting basic operations and interactions with variables.
|
"""Mathematical vector class supporting basic operations and interactions with values.
|
||||||
"""
|
"""
|
||||||
def __init__(self, values: Iterable[TNum | variable[TNum]]):
|
def __init__(self, values: Iterable[TNum | value[TNum]]):
|
||||||
"""Create a vector with given values and variables.
|
"""Create a vector with given values.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
values: iterable of constant values and variables
|
values: iterable of constant values
|
||||||
"""
|
"""
|
||||||
self.values: tuple[variable[TNum] | TNum, ...] = tuple(values)
|
self.values: tuple[value[TNum] | TNum, ...] = tuple(values)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"vector({self.values})"
|
return f"vector({self.values})"
|
||||||
|
|
@ -31,10 +31,10 @@ class vector(Generic[TNum]):
|
||||||
return len(self.values)
|
return len(self.values)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, index: int) -> variable[TNum] | TNum: ...
|
def __getitem__(self, index: int) -> value[TNum] | TNum: ...
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, index: slice) -> 'vector[TNum]': ...
|
def __getitem__(self, index: slice) -> 'vector[TNum]': ...
|
||||||
def __getitem__(self, index: int | slice) -> 'vector[TNum] | variable[TNum] | TNum':
|
def __getitem__(self, index: int | slice) -> 'vector[TNum] | value[TNum] | TNum':
|
||||||
if isinstance(index, slice):
|
if isinstance(index, slice):
|
||||||
return vector(self.values[index])
|
return vector(self.values[index])
|
||||||
return self.values[index]
|
return self.values[index]
|
||||||
|
|
@ -42,7 +42,7 @@ class vector(Generic[TNum]):
|
||||||
def __neg__(self) -> 'vector[TNum]':
|
def __neg__(self) -> 'vector[TNum]':
|
||||||
return vector(-a for a in self.values)
|
return vector(-a for a in self.values)
|
||||||
|
|
||||||
def __iter__(self) -> Iterator[variable[TNum] | TNum]:
|
def __iter__(self) -> Iterator[value[TNum] | TNum]:
|
||||||
return iter(self.values)
|
return iter(self.values)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
|
|
@ -62,7 +62,7 @@ class vector(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
def __radd__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self: 'vector[int]', other: variable[int] | int) -> 'vector[int]': ...
|
def __radd__(self: 'vector[int]', other: value[int] | int) -> 'vector[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __radd__(self, other: VecNumLike) -> 'vector[Any]': ...
|
def __radd__(self, other: VecNumLike) -> 'vector[Any]': ...
|
||||||
def __radd__(self, other: Any) -> Any:
|
def __radd__(self, other: Any) -> Any:
|
||||||
|
|
@ -85,7 +85,7 @@ class vector(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
def __rsub__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self: 'vector[int]', other: variable[int] | int) -> 'vector[int]': ...
|
def __rsub__(self: 'vector[int]', other: value[int] | int) -> 'vector[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rsub__(self, other: VecNumLike) -> 'vector[Any]': ...
|
def __rsub__(self, other: VecNumLike) -> 'vector[Any]': ...
|
||||||
def __rsub__(self, other: VecNumLike) -> Any:
|
def __rsub__(self, other: VecNumLike) -> Any:
|
||||||
|
|
@ -111,7 +111,7 @@ class vector(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
def __rmul__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self: 'vector[int]', other: variable[int] | int) -> 'vector[int]': ...
|
def __rmul__(self: 'vector[int]', other: value[int] | int) -> 'vector[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rmul__(self, other: VecNumLike) -> 'vector[Any]': ...
|
def __rmul__(self, other: VecNumLike) -> 'vector[Any]': ...
|
||||||
def __rmul__(self, other: VecNumLike) -> Any:
|
def __rmul__(self, other: VecNumLike) -> Any:
|
||||||
|
|
@ -134,7 +134,7 @@ class vector(Generic[TNum]):
|
||||||
@overload
|
@overload
|
||||||
def __rpow__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
def __rpow__(self: 'vector[float]', other: VecNumLike) -> 'vector[float]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rpow__(self: 'vector[int]', other: variable[int] | int) -> 'vector[int]': ...
|
def __rpow__(self: 'vector[int]', other: value[int] | int) -> 'vector[int]': ...
|
||||||
@overload
|
@overload
|
||||||
def __rpow__(self, other: VecNumLike) -> 'vector[Any]': ...
|
def __rpow__(self, other: VecNumLike) -> 'vector[Any]': ...
|
||||||
def __rpow__(self, other: VecNumLike) -> Any:
|
def __rpow__(self, other: VecNumLike) -> Any:
|
||||||
|
|
@ -153,26 +153,26 @@ class vector(Generic[TNum]):
|
||||||
return vector(other / a for a in self.values)
|
return vector(other / a for a in self.values)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def dot(self: 'vector[int]', other: 'vector[int]') -> int | variable[int]: ...
|
def dot(self: 'vector[int]', other: 'vector[int]') -> int | value[int]: ...
|
||||||
@overload
|
@overload
|
||||||
def dot(self, other: 'vector[float]') -> float | variable[float]: ...
|
def dot(self, other: 'vector[float]') -> float | value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def dot(self: 'vector[float]', other: 'vector[int] | vector[float]') -> float | variable[float]: ...
|
def dot(self: 'vector[float]', other: 'vector[int] | vector[float]') -> float | value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def dot(self, other: 'vector[int] | vector[float]') -> float | int | variable[float] | variable[int]: ...
|
def dot(self, other: 'vector[int] | vector[float]') -> float | int | value[float] | value[int]: ...
|
||||||
def dot(self, other: 'vector[int] | vector[float]') -> Any:
|
def dot(self, other: 'vector[int] | vector[float]') -> Any:
|
||||||
assert len(self.values) == len(other.values), "Vectors must be of same length."
|
assert len(self.values) == len(other.values), "Vectors must be of same length."
|
||||||
return mixed_sum(a * b for a, b in zip(self.values, other.values))
|
return mixed_sum(a * b for a, b in zip(self.values, other.values))
|
||||||
|
|
||||||
# @ operator
|
# @ operator
|
||||||
@overload
|
@overload
|
||||||
def __matmul__(self: 'vector[int]', other: 'vector[int]') -> int | variable[int]: ...
|
def __matmul__(self: 'vector[int]', other: 'vector[int]') -> int | value[int]: ...
|
||||||
@overload
|
@overload
|
||||||
def __matmul__(self, other: 'vector[float]') -> float | variable[float]: ...
|
def __matmul__(self, other: 'vector[float]') -> float | value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def __matmul__(self: 'vector[float]', other: 'vector[int] | vector[float]') -> float | variable[float]: ...
|
def __matmul__(self: 'vector[float]', other: 'vector[int] | vector[float]') -> float | value[float]: ...
|
||||||
@overload
|
@overload
|
||||||
def __matmul__(self, other: 'vector[int] | vector[float]') -> float | int | variable[float] | variable[int]: ...
|
def __matmul__(self, other: 'vector[int] | vector[float]') -> float | int | value[float] | value[int]: ...
|
||||||
def __matmul__(self, other: 'vector[int] | vector[float]') -> Any:
|
def __matmul__(self, other: 'vector[int] | vector[float]') -> Any:
|
||||||
return self.dot(other)
|
return self.dot(other)
|
||||||
|
|
||||||
|
|
@ -229,14 +229,14 @@ class vector(Generic[TNum]):
|
||||||
return (len(self.values),)
|
return (len(self.values),)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def sum(self: 'vector[int]') -> int | variable[int]: ...
|
def sum(self: 'vector[int]') -> int | value[int]: ...
|
||||||
@overload
|
@overload
|
||||||
def sum(self: 'vector[float]') -> float | variable[float]: ...
|
def sum(self: 'vector[float]') -> float | value[float]: ...
|
||||||
def sum(self) -> Any:
|
def sum(self) -> Any:
|
||||||
"""Sum of all vector elements."""
|
"""Sum of all vector elements."""
|
||||||
return mixed_sum(self.values)
|
return mixed_sum(self.values)
|
||||||
|
|
||||||
def magnitude(self) -> 'float | variable[float]':
|
def magnitude(self) -> 'float | value[float]':
|
||||||
"""Magnitude (length) of the vector."""
|
"""Magnitude (length) of the vector."""
|
||||||
s = mixed_sum(a * a for a in self.values)
|
s = mixed_sum(a * a for a in self.values)
|
||||||
return cp.sqrt(s)
|
return cp.sqrt(s)
|
||||||
|
|
@ -247,12 +247,12 @@ class vector(Generic[TNum]):
|
||||||
return self / mag
|
return self / mag
|
||||||
|
|
||||||
def homogenize(self) -> 'vector[TNum]':
|
def homogenize(self) -> 'vector[TNum]':
|
||||||
if any(isinstance(val, variable) for val in self.values):
|
if any(isinstance(val, value) for val in self.values):
|
||||||
return vector(mixed_homogenize(self))
|
return vector(mixed_homogenize(self))
|
||||||
else:
|
else:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def map(self, func: Callable[[Any], variable[U] | U]) -> 'vector[U]':
|
def map(self, func: Callable[[Any], value[U] | U]) -> 'vector[U]':
|
||||||
"""Applies a function to each element of the vector and returns a new vector."""
|
"""Applies a function to each element of the vector and returns a new vector."""
|
||||||
return vector(func(x) for x in self.values)
|
return vector(func(x) for x in self.values)
|
||||||
|
|
||||||
|
|
@ -262,18 +262,18 @@ def cross_product(v1: vector[float], v2: vector[float]) -> vector[float]:
|
||||||
return v1.cross(v2)
|
return v1.cross(v2)
|
||||||
|
|
||||||
|
|
||||||
def dot_product(v1: vector[float], v2: vector[float]) -> 'float | variable[float]':
|
def dot_product(v1: vector[float], v2: vector[float]) -> 'float | value[float]':
|
||||||
"""Calculate the dot product of two vectors."""
|
"""Calculate the dot product of two vectors."""
|
||||||
return v1.dot(v2)
|
return v1.dot(v2)
|
||||||
|
|
||||||
|
|
||||||
def distance(v1: vector[float], v2: vector[float]) -> 'float | variable[float]':
|
def distance(v1: vector[float], v2: vector[float]) -> 'float | value[float]':
|
||||||
"""Calculate the Euclidean distance between two vectors."""
|
"""Calculate the Euclidean distance between two vectors."""
|
||||||
diff = v1 - v2
|
diff = v1 - v2
|
||||||
return diff.magnitude()
|
return diff.magnitude()
|
||||||
|
|
||||||
|
|
||||||
def scalar_projection(v1: vector[float], v2: vector[float]) -> 'float | variable[float]':
|
def scalar_projection(v1: vector[float], v2: vector[float]) -> 'float | value[float]':
|
||||||
"""Calculate the scalar projection of v1 onto v2."""
|
"""Calculate the scalar projection of v1 onto v2."""
|
||||||
dot_prod = v1.dot(v2)
|
dot_prod = v1.dot(v2)
|
||||||
mag_v2 = v2.magnitude() + epsilon
|
mag_v2 = v2.magnitude() + epsilon
|
||||||
|
|
@ -288,7 +288,7 @@ def vector_projection(v1: vector[float], v2: vector[float]) -> vector[float]:
|
||||||
return v2 * scalar_proj
|
return v2 * scalar_proj
|
||||||
|
|
||||||
|
|
||||||
def angle_between(v1: vector[float], v2: vector[float]) -> 'float | variable[float]':
|
def angle_between(v1: vector[float], v2: vector[float]) -> 'float | value[float]':
|
||||||
"""Calculate the angle in radians between two vectors."""
|
"""Calculate the angle in radians between two vectors."""
|
||||||
dot_prod = v1.dot(v2)
|
dot_prod = v1.dot(v2)
|
||||||
mag_v1 = v1.magnitude()
|
mag_v1 = v1.magnitude()
|
||||||
|
|
@ -297,7 +297,7 @@ def angle_between(v1: vector[float], v2: vector[float]) -> 'float | variable[flo
|
||||||
return cp.acos(cos_angle)
|
return cp.acos(cos_angle)
|
||||||
|
|
||||||
|
|
||||||
def rotate_vector(v: vector[float], axis: vector[float], angle: 'float | variable[float]') -> vector[float]:
|
def rotate_vector(v: vector[float], axis: vector[float], angle: 'float | value[float]') -> vector[float]:
|
||||||
"""Rotate vector v around a given axis by a specified angle using Rodrigues' rotation formula."""
|
"""Rotate vector v around a given axis by a specified angle using Rodrigues' rotation formula."""
|
||||||
k = axis.normalize()
|
k = axis.normalize()
|
||||||
cos_angle = cp.cos(angle)
|
cos_angle = cp.cos(angle)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
from . import variable, vector
|
from . import value, vector
|
||||||
from ._basic_types import iif, unifloat
|
from ._basic_types import iif, unifloat
|
||||||
from._helper_types import TNum
|
from._helper_types import TNum
|
||||||
from typing import Any, Iterable
|
from typing import Any, Iterable
|
||||||
|
|
||||||
|
|
||||||
def homogenize_vector(input_values: Iterable[TNum | variable[TNum]]) -> Iterable[TNum] | Iterable[variable[TNum]]:
|
def homogenize_vector(input_values: Iterable[TNum | value[TNum]]) -> Iterable[TNum] | Iterable[value[TNum]]:
|
||||||
input_list = list(input_values)
|
input_list = list(input_values)
|
||||||
if any(isinstance(val, variable) for val in input_list):
|
if any(isinstance(val, value) for val in input_list):
|
||||||
return (v if isinstance(v, variable) else variable(v) for v in input_list)
|
return (v if isinstance(v, value) else value(v) for v in input_list)
|
||||||
else:
|
else:
|
||||||
return (v for v in input_list if not isinstance(v, variable))
|
return (v for v in input_list if not isinstance(v, value))
|
||||||
|
|
||||||
|
|
||||||
def _inv_argsort(input_vector: vector[TNum]) -> vector[int]:
|
def _inv_argsort(input_vector: vector[TNum]) -> vector[int]:
|
||||||
|
|
@ -31,7 +31,7 @@ def argsort(input_vector: vector[TNum]) -> vector[int]:
|
||||||
return _inv_argsort(_inv_argsort(input_vector))
|
return _inv_argsort(_inv_argsort(input_vector))
|
||||||
|
|
||||||
|
|
||||||
def median(input_vector: vector[TNum]) -> TNum | variable[TNum]:
|
def median(input_vector: vector[TNum]) -> TNum | value[TNum]:
|
||||||
"""
|
"""
|
||||||
Applies a median filter to the input vector and returns the median as a unifloat.
|
Applies a median filter to the input vector and returns the median as a unifloat.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ def cp_vs_python(path: str):
|
||||||
#v_size = 400
|
#v_size = 400
|
||||||
iter_size = 30000
|
iter_size = 30000
|
||||||
|
|
||||||
v1 = cp.vector(cp.variable(float(v)) for v in range(v_size))
|
v1 = cp.vector(cp.value(float(v)) for v in range(v_size))
|
||||||
v2 = cp.vector(cp.variable(float(v)) for v in [5]*v_size)
|
v2 = cp.vector(cp.value(float(v)) for v in [5]*v_size)
|
||||||
|
|
||||||
v3 = sum((v1 + i) @ v2 for i in range(sum_size))
|
v3 = sum((v1 + i) @ v2 for i in range(sum_size))
|
||||||
|
|
||||||
|
|
@ -95,8 +95,8 @@ def cp_vs_python_sparse(path: str = 'benchmark_results_001_sparse.json'):
|
||||||
#v_size = 400
|
#v_size = 400
|
||||||
iter_size = 3000
|
iter_size = 3000
|
||||||
|
|
||||||
v1 = cp.vector(cp.variable(float(v)) for v in range(v_size))
|
v1 = cp.vector(cp.value(float(v)) for v in range(v_size))
|
||||||
v2 = cp.vector(cp.variable(float(v)) for v in [5]*v_size)
|
v2 = cp.vector(cp.value(float(v)) for v in [5]*v_size)
|
||||||
|
|
||||||
test = cp.vector(np.linspace(0, 1, v_size))
|
test = cp.vector(np.linspace(0, 1, v_size))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable
|
from copapy import value
|
||||||
from copapy.backend import Write
|
from copapy.backend import Write
|
||||||
import copapy.backend as cpb
|
import copapy.backend as cpb
|
||||||
|
|
||||||
|
|
@ -21,8 +21,8 @@ def test_ast_generation():
|
||||||
#r2 = i1 + 9
|
#r2 = i1 + 9
|
||||||
#out = [Write(r1), Write(r2)]
|
#out = [Write(r1), Write(r2)]
|
||||||
|
|
||||||
c1 = variable(4)
|
c1 = value(4)
|
||||||
c2 = variable(2)
|
c2 = value(2)
|
||||||
#i1 = c1 * 2
|
#i1 = c1 * 2
|
||||||
#r1 = i1 + 7 + (c2 + 7 * 9)
|
#r1 = i1 + 7 + (c2 + 7 * 9)
|
||||||
#r2 = i1 + 9
|
#r2 = i1 + 9
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable, grad
|
from copapy import value, grad
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
@ -6,8 +6,8 @@ import pytest
|
||||||
def test_autograd():
|
def test_autograd():
|
||||||
# Validate against micrograd results from Andrej Karpathy
|
# Validate against micrograd results from Andrej Karpathy
|
||||||
# https://github.com/karpathy/micrograd/blob/master/test/test_engine.py
|
# https://github.com/karpathy/micrograd/blob/master/test/test_engine.py
|
||||||
a = variable(-4.0)
|
a = value(-4.0)
|
||||||
b = variable(2.0)
|
b = value(2.0)
|
||||||
c = a + b
|
c = a + b
|
||||||
d = a * b + b**3
|
d = a * b + b**3
|
||||||
c += c + 1
|
c += c + 1
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable
|
from copapy import value
|
||||||
from copapy.backend import Write, compile_to_dag, add_read_command
|
from copapy.backend import Write, compile_to_dag, add_read_command
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -20,7 +20,7 @@ def test_compile():
|
||||||
test_vals = [0.0, -1.5, -2.0, -2.5, -3.0]
|
test_vals = [0.0, -1.5, -2.0, -2.5, -3.0]
|
||||||
|
|
||||||
# Function with no passing-on-jump as last instruction:
|
# Function with no passing-on-jump as last instruction:
|
||||||
ret_test = [r for v in test_vals for r in (cp.tan(variable(v)),)]
|
ret_test = [r for v in test_vals for r in (cp.tan(value(v)),)]
|
||||||
|
|
||||||
out = [Write(r) for r in ret_test]
|
out = [Write(r) for r in ret_test]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ from copapy._compiler import patch_entry, CPConstant, get_aux_func_layout
|
||||||
|
|
||||||
|
|
||||||
def test_timing_compiler():
|
def test_timing_compiler():
|
||||||
t1 = cp.vector([10, 11]*128) + cp.vector(cp.variable(v) for v in range(256))
|
t1 = cp.vector([10, 11]*128) + cp.vector(cp.value(v) for v in range(256))
|
||||||
#t2 = t1.sum()
|
#t2 = t1.sum()
|
||||||
t3 = cp.vector(cp.variable(1 / (v + 1)) for v in range(256))
|
t3 = cp.vector(cp.value(1 / (v + 1)) for v in range(256))
|
||||||
t5 = ((t3 * t1) * 2).magnitude()
|
t5 = ((t3 * t1) * 2).magnitude()
|
||||||
out = [Write(t5)]
|
out = [Write(t5)]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,10 @@ def test_compile():
|
||||||
#ret = function(c1, c2)
|
#ret = function(c1, c2)
|
||||||
#ret = [c1 // 3.3 + 5]
|
#ret = [c1 // 3.3 + 5]
|
||||||
|
|
||||||
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.variable(v) for v in range(3))
|
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.value(v) for v in range(3))
|
||||||
t2 = t1.sum()
|
t2 = t1.sum()
|
||||||
|
|
||||||
t3 = cp.vector(cp.variable(1 / (v + 1)) for v in range(3))
|
t3 = cp.vector(cp.value(1 / (v + 1)) for v in range(3))
|
||||||
t4 = ((t3 * t1) * 2).sum()
|
t4 = ((t3 * t1) * 2).sum()
|
||||||
t5 = ((t3 * t1) * 2).magnitude()
|
t5 = ((t3 * t1) * 2).magnitude()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ def function(c1: NumLike, c2: NumLike) -> tuple[NumLike, ...]:
|
||||||
|
|
||||||
@pytest.mark.runner
|
@pytest.mark.runner
|
||||||
def test_compile():
|
def test_compile():
|
||||||
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.variable(v) for v in range(3))
|
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.value(v) for v in range(3))
|
||||||
t2 = t1.sum()
|
t2 = t1.sum()
|
||||||
|
|
||||||
t3 = cp.vector(cp.variable(1 / (v + 1)) for v in range(3))
|
t3 = cp.vector(cp.value(1 / (v + 1)) for v in range(3))
|
||||||
t4 = ((t3 * t1) * 2).sum()
|
t4 = ((t3 * t1) * 2).sum()
|
||||||
t5 = ((t3 * t1) * 2).magnitude()
|
t5 = ((t3 * t1) * 2).magnitude()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ def function(c1: NumLike, c2: NumLike) -> tuple[NumLike, ...]:
|
||||||
|
|
||||||
@pytest.mark.runner
|
@pytest.mark.runner
|
||||||
def test_compile():
|
def test_compile():
|
||||||
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.variable(v) for v in range(3))
|
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.value(v) for v in range(3))
|
||||||
t2 = t1.sum()
|
t2 = t1.sum()
|
||||||
|
|
||||||
t3 = cp.vector(cp.variable(1 / (v + 1)) for v in range(3))
|
t3 = cp.vector(cp.value(1 / (v + 1)) for v in range(3))
|
||||||
t4 = ((t3 * t1) * 2).sum()
|
t4 = ((t3 * t1) * 2).sum()
|
||||||
t5 = ((t3 * t1) * 2).magnitude()
|
t5 = ((t3 * t1) * 2).magnitude()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable, NumLike
|
from copapy import value, NumLike
|
||||||
from copapy.backend import Write, compile_to_dag
|
from copapy.backend import Write, compile_to_dag
|
||||||
import copapy
|
import copapy
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -22,7 +22,7 @@ def function(c1: NumLike) -> list[NumLike]:
|
||||||
@pytest.mark.runner
|
@pytest.mark.runner
|
||||||
def test_compile():
|
def test_compile():
|
||||||
|
|
||||||
c1 = variable(16)
|
c1 = value(16)
|
||||||
|
|
||||||
ret = function(c1)
|
ret = function(c1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable
|
from copapy import value
|
||||||
from copapy.backend import Write, compile_to_dag, add_read_command
|
from copapy.backend import Write, compile_to_dag, add_read_command
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -18,7 +18,7 @@ def run_command(command: list[str]) -> str:
|
||||||
def test_compile_sqrt():
|
def test_compile_sqrt():
|
||||||
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
||||||
|
|
||||||
ret = [r for v in test_vals for r in (cp.sqrt(variable(v)),)]
|
ret = [r for v in test_vals for r in (cp.sqrt(value(v)),)]
|
||||||
|
|
||||||
|
|
||||||
out = [Write(r) for r in ret]
|
out = [Write(r) for r in ret]
|
||||||
|
|
@ -52,7 +52,7 @@ def test_compile_sqrt():
|
||||||
def test_compile_log():
|
def test_compile_log():
|
||||||
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
||||||
|
|
||||||
ret = [r for v in test_vals for r in (cp.log(variable(v)),)]
|
ret = [r for v in test_vals for r in (cp.log(value(v)),)]
|
||||||
|
|
||||||
|
|
||||||
out = [Write(r) for r in ret]
|
out = [Write(r) for r in ret]
|
||||||
|
|
@ -86,7 +86,7 @@ def test_compile_log():
|
||||||
def test_compile_sin():
|
def test_compile_sin():
|
||||||
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
||||||
|
|
||||||
ret = [r for v in test_vals for r in (cp.sin(variable(v)),)]
|
ret = [r for v in test_vals for r in (cp.sin(value(v)),)]
|
||||||
|
|
||||||
|
|
||||||
out = [Write(r) for r in ret]
|
out = [Write(r) for r in ret]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable, Target, NumLike
|
from copapy import value, Target, NumLike
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ def function(c1: NumLike) -> list[NumLike]:
|
||||||
|
|
||||||
def test_compile():
|
def test_compile():
|
||||||
|
|
||||||
c1 = variable(16)
|
c1 = value(16)
|
||||||
|
|
||||||
ret = function(c1)
|
ret = function(c1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable, Target
|
from copapy import value, Target
|
||||||
import pytest
|
import pytest
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
import math as ma
|
import math as ma
|
||||||
|
|
@ -7,8 +7,8 @@ import warnings
|
||||||
def test_fine():
|
def test_fine():
|
||||||
a_i = 9
|
a_i = 9
|
||||||
a_f = 2.5
|
a_f = 2.5
|
||||||
c_i = variable(a_i)
|
c_i = value(a_i)
|
||||||
c_f = variable(a_f)
|
c_f = value(a_f)
|
||||||
# c_b = variable(True)
|
# c_b = variable(True)
|
||||||
|
|
||||||
ret_test = (c_f ** 2,
|
ret_test = (c_f ** 2,
|
||||||
|
|
@ -49,7 +49,7 @@ def test_fine():
|
||||||
print('* finished')
|
print('* finished')
|
||||||
|
|
||||||
for test, val2, ref, name in zip(ret_test, re2_test, ret_refe, ('^2', '**-1', 'sqrt_int', 'sqrt_float', 'sin', 'cos', 'tan')):
|
for test, val2, ref, name in zip(ret_test, re2_test, ret_refe, ('^2', '**-1', 'sqrt_int', 'sqrt_float', 'sin', 'cos', 'tan')):
|
||||||
assert isinstance(test, cp.variable)
|
assert isinstance(test, cp.value)
|
||||||
val = tg.read_value(test)
|
val = tg.read_value(test)
|
||||||
print('+', val, ref, type(val), test.dtype)
|
print('+', val, ref, type(val), test.dtype)
|
||||||
#for t in (int, float, bool):
|
#for t in (int, float, bool):
|
||||||
|
|
@ -63,7 +63,7 @@ def test_trig_precision():
|
||||||
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0,
|
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0,
|
||||||
-0.0001, -0.1, -0.5, -1.0, -1.5, -2.0, -2.5, -3.0, -3.5, -4.0, -4.5, -5.0, -5.5, -6.0, -6.28318530718, -100.0, -1000.0, -100000.0]
|
-0.0001, -0.1, -0.5, -1.0, -1.5, -2.0, -2.5, -3.0, -3.5, -4.0, -4.5, -5.0, -5.5, -6.0, -6.28318530718, -100.0, -1000.0, -100000.0]
|
||||||
|
|
||||||
ret_test = [r for v in test_vals for r in (cp.sin(variable(v)), cp.cos(variable(v)), cp.tan(variable(v)))]
|
ret_test = [r for v in test_vals for r in (cp.sin(value(v)), cp.cos(value(v)), cp.tan(value(v)))]
|
||||||
ret_refe = [r for v in test_vals for r in (ma.sin(v), ma.cos(v), ma.tan(v))]
|
ret_refe = [r for v in test_vals for r in (ma.sin(v), ma.cos(v), ma.tan(v))]
|
||||||
|
|
||||||
tg = Target()
|
tg = Target()
|
||||||
|
|
@ -72,7 +72,7 @@ def test_trig_precision():
|
||||||
|
|
||||||
for i, (v, test, ref) in enumerate(zip(test_vals, ret_test, ret_refe)):
|
for i, (v, test, ref) in enumerate(zip(test_vals, ret_test, ret_refe)):
|
||||||
func_name = ['sin', 'cos', 'tan'][i % 3]
|
func_name = ['sin', 'cos', 'tan'][i % 3]
|
||||||
assert isinstance(test, cp.variable)
|
assert isinstance(test, cp.value)
|
||||||
val = tg.read_value(test)
|
val = tg.read_value(test)
|
||||||
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
||||||
assert val == pytest.approx(ref, abs=1e-3), f"Result of {func_name} for input {test_vals[i // 3]} does not match: {val} and reference: {ref} (value: {v})" # pyright: ignore[reportUnknownMemberType]
|
assert val == pytest.approx(ref, abs=1e-3), f"Result of {func_name} for input {test_vals[i // 3]} does not match: {val} and reference: {ref} (value: {v})" # pyright: ignore[reportUnknownMemberType]
|
||||||
|
|
@ -85,11 +85,11 @@ def test_arcus_trig_precision():
|
||||||
test_vals = [0.0, 0.01, 0.1, 0.5, 0.7, 0.9, 0.95,
|
test_vals = [0.0, 0.01, 0.1, 0.5, 0.7, 0.9, 0.95,
|
||||||
-0.01, -0.1, -0.5, -0.7, -0.9, 0.95]
|
-0.01, -0.1, -0.5, -0.7, -0.9, 0.95]
|
||||||
|
|
||||||
ret_test = [r for v in test_vals for r in (cp.asin(variable(v)),
|
ret_test = [r for v in test_vals for r in (cp.asin(value(v)),
|
||||||
cp.acos(variable(v)),
|
cp.acos(value(v)),
|
||||||
cp.atan(variable(v)),
|
cp.atan(value(v)),
|
||||||
cp.atan2(variable(v), variable(3)),
|
cp.atan2(value(v), value(3)),
|
||||||
cp.atan2(variable(v), variable(-3)),)]
|
cp.atan2(value(v), value(-3)),)]
|
||||||
ret_refe = [r for v in test_vals for r in (ma.asin(v),
|
ret_refe = [r for v in test_vals for r in (ma.asin(v),
|
||||||
ma.acos(v),
|
ma.acos(v),
|
||||||
ma.atan(v),
|
ma.atan(v),
|
||||||
|
|
@ -102,7 +102,7 @@ def test_arcus_trig_precision():
|
||||||
|
|
||||||
for i, (test, ref) in enumerate(zip(ret_test, ret_refe)):
|
for i, (test, ref) in enumerate(zip(ret_test, ret_refe)):
|
||||||
func_name = ['asin', 'acos', 'atan', 'atan2[1]', 'atan2[2]'][i % 5]
|
func_name = ['asin', 'acos', 'atan', 'atan2[1]', 'atan2[2]'][i % 5]
|
||||||
assert isinstance(test, cp.variable)
|
assert isinstance(test, cp.value)
|
||||||
val = tg.read_value(test)
|
val = tg.read_value(test)
|
||||||
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
||||||
#assert val == pytest.approx(ref, abs=1e-5), f"Result of {func_name} for input {test_vals[i // 5]} does not match: {val} and reference: {ref}" # pyright: ignore[reportUnknownMemberType]
|
#assert val == pytest.approx(ref, abs=1e-5), f"Result of {func_name} for input {test_vals[i // 5]} does not match: {val} and reference: {ref}" # pyright: ignore[reportUnknownMemberType]
|
||||||
|
|
@ -113,7 +113,7 @@ def test_arcus_trig_precision():
|
||||||
def test_sqrt_precision():
|
def test_sqrt_precision():
|
||||||
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
test_vals = [0.0, 0.0001, 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.28318530718, 100.0, 1000.0, 100000.0]
|
||||||
|
|
||||||
ret_test = [r for v in test_vals for r in (cp.sqrt(variable(v)),)]
|
ret_test = [r for v in test_vals for r in (cp.sqrt(value(v)),)]
|
||||||
ret_refe = [r for v in test_vals for r in (cp.sqrt(v),)]
|
ret_refe = [r for v in test_vals for r in (cp.sqrt(v),)]
|
||||||
|
|
||||||
tg = Target()
|
tg = Target()
|
||||||
|
|
@ -122,7 +122,7 @@ def test_sqrt_precision():
|
||||||
|
|
||||||
for i, (test, ref) in enumerate(zip(ret_test, ret_refe)):
|
for i, (test, ref) in enumerate(zip(ret_test, ret_refe)):
|
||||||
func_name = 'sqrt'
|
func_name = 'sqrt'
|
||||||
assert isinstance(test, cp.variable)
|
assert isinstance(test, cp.value)
|
||||||
val = tg.read_value(test)
|
val = tg.read_value(test)
|
||||||
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
||||||
assert val == pytest.approx(ref, rel=1e-5), f"Result of {func_name} for input {test_vals[i]} does not match: {val} and reference: {ref}" # pyright: ignore[reportUnknownMemberType]
|
assert val == pytest.approx(ref, rel=1e-5), f"Result of {func_name} for input {test_vals[i]} does not match: {val} and reference: {ref}" # pyright: ignore[reportUnknownMemberType]
|
||||||
|
|
@ -135,8 +135,8 @@ def test_log_exp_precision():
|
||||||
test_vals = [0.1, 0.5, 0.9, 0.999, 1.0, 2.5,
|
test_vals = [0.1, 0.5, 0.9, 0.999, 1.0, 2.5,
|
||||||
-0.1, -0.5, -0.9, -0.999, -1.0, 2.5]
|
-0.1, -0.5, -0.9, -0.999, -1.0, 2.5]
|
||||||
|
|
||||||
ret_test = [r for v in test_vals for r in (cp.log(variable(abs(v))),
|
ret_test = [r for v in test_vals for r in (cp.log(value(abs(v))),
|
||||||
cp.exp(variable(v)))]
|
cp.exp(value(v)))]
|
||||||
ret_refe = [r for v in test_vals for r in (ma.log(abs(v)),
|
ret_refe = [r for v in test_vals for r in (ma.log(abs(v)),
|
||||||
ma.exp(v))]
|
ma.exp(v))]
|
||||||
|
|
||||||
|
|
@ -146,7 +146,7 @@ def test_log_exp_precision():
|
||||||
|
|
||||||
for i, (test, ref) in enumerate(zip(ret_test, ret_refe)):
|
for i, (test, ref) in enumerate(zip(ret_test, ret_refe)):
|
||||||
func_name = ['log', 'exp'][i % 2]
|
func_name = ['log', 'exp'][i % 2]
|
||||||
assert isinstance(test, cp.variable)
|
assert isinstance(test, cp.value)
|
||||||
val = tg.read_value(test)
|
val = tg.read_value(test)
|
||||||
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
print(f"+ Result of {func_name}: {val}; reference: {ref}")
|
||||||
assert val == pytest.approx(ref, abs=1e-5), f"Result of {func_name} for input {test_vals[i // 2]} does not match: {val} and reference: {ref}" # pyright: ignore[reportUnknownMemberType]
|
assert val == pytest.approx(ref, abs=1e-5), f"Result of {func_name} for input {test_vals[i // 2]} does not match: {val} and reference: {ref}" # pyright: ignore[reportUnknownMemberType]
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ def test_matrix_init():
|
||||||
|
|
||||||
def test_matrix_with_variables():
|
def test_matrix_with_variables():
|
||||||
"""Test matrix initialization with variables"""
|
"""Test matrix initialization with variables"""
|
||||||
m1 = cp.matrix([[cp.variable(1), 2], [3, cp.variable(4)]])
|
m1 = cp.matrix([[cp.value(1), 2], [3, cp.value(4)]])
|
||||||
assert m1.rows == 2
|
assert m1.rows == 2
|
||||||
assert m1.cols == 2
|
assert m1.cols == 2
|
||||||
assert isinstance(m1[0][0], cp.variable)
|
assert isinstance(m1[0][0], cp.value)
|
||||||
assert isinstance(m1[1][1], cp.variable)
|
assert isinstance(m1[1][1], cp.value)
|
||||||
|
|
||||||
|
|
||||||
def test_matrix_addition():
|
def test_matrix_addition():
|
||||||
|
|
@ -201,12 +201,12 @@ def test_matrix_map():
|
||||||
|
|
||||||
def test_matrix_homogenize():
|
def test_matrix_homogenize():
|
||||||
"""Test homogenizing matrix (converting to all variables)"""
|
"""Test homogenizing matrix (converting to all variables)"""
|
||||||
m = cp.matrix([[1, cp.variable(2)], [3, 4]])
|
m = cp.matrix([[1, cp.value(2)], [3, 4]])
|
||||||
m_homo = m.homogenize()
|
m_homo = m.homogenize()
|
||||||
|
|
||||||
for row in m_homo:
|
for row in m_homo:
|
||||||
for elem in row:
|
for elem in row:
|
||||||
assert isinstance(elem, cp.variable)
|
assert isinstance(elem, cp.value)
|
||||||
|
|
||||||
|
|
||||||
def test_identity_matrix():
|
def test_identity_matrix():
|
||||||
|
|
@ -254,8 +254,8 @@ def test_diagonal_matrix():
|
||||||
|
|
||||||
def test_matrix_with_variables_compiled():
|
def test_matrix_with_variables_compiled():
|
||||||
"""Test matrix operations with variables in compilation"""
|
"""Test matrix operations with variables in compilation"""
|
||||||
m = cp.matrix([[cp.variable(1), 2], [3, cp.variable(4)]])
|
m = cp.matrix([[cp.value(1), 2], [3, cp.value(4)]])
|
||||||
v = cp.vector([cp.variable(5), 6])
|
v = cp.vector([cp.value(5), 6])
|
||||||
result = m @ v
|
result = m @ v
|
||||||
|
|
||||||
# result[0] = 1*5 + 2*6 = 17
|
# result[0] = 1*5 + 2*6 = 17
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable, Target, NumLike, iif
|
from copapy import value, Target, NumLike, iif
|
||||||
import pytest
|
import pytest
|
||||||
import copapy
|
import copapy
|
||||||
|
|
||||||
|
|
@ -42,11 +42,11 @@ def iiftests(c1: NumLike) -> list[NumLike]:
|
||||||
|
|
||||||
|
|
||||||
def test_compile():
|
def test_compile():
|
||||||
c_i = variable(9)
|
c_i = value(9)
|
||||||
c_f = variable(1.111)
|
c_f = value(1.111)
|
||||||
c_b = variable(True)
|
c_b = value(True)
|
||||||
|
|
||||||
ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [variable(9) % 2] + iiftests(c_i) + iiftests(c_f)
|
ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [value(9) % 2] + iiftests(c_i) + iiftests(c_f)
|
||||||
ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111)
|
ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111)
|
||||||
|
|
||||||
tg = Target()
|
tg = Target()
|
||||||
|
|
@ -57,7 +57,7 @@ def test_compile():
|
||||||
print('* finished')
|
print('* finished')
|
||||||
|
|
||||||
for test, ref in zip(ret_test, ret_ref):
|
for test, ref in zip(ret_test, ret_ref):
|
||||||
assert isinstance(test, copapy.variable)
|
assert isinstance(test, copapy.value)
|
||||||
val = tg.read_value(test)
|
val = tg.read_value(test)
|
||||||
print('+', val, ref, test.dtype)
|
print('+', val, ref, test.dtype)
|
||||||
for t in (int, float, bool):
|
for t in (int, float, bool):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import NumLike, iif, variable
|
from copapy import NumLike, iif, value
|
||||||
from copapy.backend import Write, compile_to_dag, add_read_command
|
from copapy.backend import Write, compile_to_dag, add_read_command
|
||||||
import subprocess
|
import subprocess
|
||||||
from copapy import _binwrite
|
from copapy import _binwrite
|
||||||
|
|
@ -84,11 +84,11 @@ def iiftests(c1: NumLike) -> list[NumLike]:
|
||||||
|
|
||||||
@pytest.mark.runner
|
@pytest.mark.runner
|
||||||
def test_compile():
|
def test_compile():
|
||||||
c_i = variable(9)
|
c_i = value(9)
|
||||||
c_f = variable(1.111)
|
c_f = value(1.111)
|
||||||
c_b = variable(True)
|
c_b = value(True)
|
||||||
|
|
||||||
ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [variable(9) % 2] + iiftests(c_i) + iiftests(c_f) + [cp.asin(c_i/10)]
|
ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [value(9) % 2] + iiftests(c_i) + iiftests(c_f) + [cp.asin(c_i/10)]
|
||||||
ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111) + [cp.asin(9/10)]
|
ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111) + [cp.asin(9/10)]
|
||||||
|
|
||||||
out = [Write(r) for r in ret_test]
|
out = [Write(r) for r in ret_test]
|
||||||
|
|
@ -145,7 +145,7 @@ def test_compile():
|
||||||
result_data = parse_results(result)
|
result_data = parse_results(result)
|
||||||
|
|
||||||
for test, ref in zip(ret_test, ret_ref):
|
for test, ref in zip(ret_test, ret_ref):
|
||||||
assert isinstance(test, variable)
|
assert isinstance(test, value)
|
||||||
address = variables[test][0]
|
address = variables[test][0]
|
||||||
data = result_data[address]
|
data = result_data[address]
|
||||||
if test.dtype == 'int':
|
if test.dtype == 'int':
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import NumLike, iif, variable
|
from copapy import NumLike, iif, value
|
||||||
from copapy.backend import Write, compile_to_dag, add_read_command
|
from copapy.backend import Write, compile_to_dag, add_read_command
|
||||||
import subprocess
|
import subprocess
|
||||||
from copapy import _binwrite
|
from copapy import _binwrite
|
||||||
|
|
@ -86,11 +86,11 @@ def iiftests(c1: NumLike) -> list[NumLike]:
|
||||||
|
|
||||||
@pytest.mark.runner
|
@pytest.mark.runner
|
||||||
def test_compile():
|
def test_compile():
|
||||||
c_i = variable(9)
|
c_i = value(9)
|
||||||
c_f = variable(1.111)
|
c_f = value(1.111)
|
||||||
c_b = variable(True)
|
c_b = value(True)
|
||||||
|
|
||||||
ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [variable(9) % 2] + iiftests(c_i) + iiftests(c_f) + [cp.asin(c_i/10)]
|
ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [value(9) % 2] + iiftests(c_i) + iiftests(c_f) + [cp.asin(c_i/10)]
|
||||||
ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111) + [cp.asin(9/10)]
|
ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111) + [cp.asin(9/10)]
|
||||||
|
|
||||||
#ret_test = (c_i * 100 // 5, c_f * 10 // 5)
|
#ret_test = (c_i * 100 // 5, c_f * 10 // 5)
|
||||||
|
|
@ -147,7 +147,7 @@ def test_compile():
|
||||||
result_data = parse_results(result)
|
result_data = parse_results(result)
|
||||||
|
|
||||||
for test, ref in zip(ret_test, ret_ref):
|
for test, ref in zip(ret_test, ret_ref):
|
||||||
assert isinstance(test, variable)
|
assert isinstance(test, value)
|
||||||
address = variables[test][0]
|
address = variables[test][0]
|
||||||
data = result_data[address]
|
data = result_data[address]
|
||||||
if test.dtype == 'int':
|
if test.dtype == 'int':
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import NumLike, iif, variable
|
from copapy import NumLike, iif, value
|
||||||
from copapy.backend import Write, compile_to_dag, add_read_command
|
from copapy.backend import Write, compile_to_dag, add_read_command
|
||||||
import subprocess
|
import subprocess
|
||||||
from copapy import _binwrite
|
from copapy import _binwrite
|
||||||
|
|
@ -77,7 +77,7 @@ def test_compile():
|
||||||
#t4 = ((t3 * t1) * 2).sum()
|
#t4 = ((t3 * t1) * 2).sum()
|
||||||
#t5 = ((t3 * t1) * 2).magnitude()
|
#t5 = ((t3 * t1) * 2).magnitude()
|
||||||
|
|
||||||
c_i = variable(9)
|
c_i = value(9)
|
||||||
#c_f = variable(1.111)
|
#c_f = variable(1.111)
|
||||||
#c_b = variable(True)
|
#c_b = variable(True)
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ def test_compile():
|
||||||
#ret_test = [cp.sin(c_i), cp.asin(variable(0.0))]
|
#ret_test = [cp.sin(c_i), cp.asin(variable(0.0))]
|
||||||
#ret_ref = [cp.sin(9), cp.asin(0.0)]
|
#ret_ref = [cp.sin(9), cp.asin(0.0)]
|
||||||
|
|
||||||
ret_test: list[variable[float]] = []
|
ret_test: list[value[float]] = []
|
||||||
ret_ref: list[float] = []
|
ret_ref: list[float] = []
|
||||||
#sval = variable(8.0)
|
#sval = variable(8.0)
|
||||||
#tval = 8.0
|
#tval = 8.0
|
||||||
|
|
@ -155,7 +155,7 @@ def test_compile():
|
||||||
result_data = parse_results(result)
|
result_data = parse_results(result)
|
||||||
|
|
||||||
for test, ref in zip(ret_test, ret_ref):
|
for test, ref in zip(ret_test, ret_ref):
|
||||||
assert isinstance(test, variable)
|
assert isinstance(test, value)
|
||||||
address = variables[test][0]
|
address = variables[test][0]
|
||||||
data = result_data[address]
|
data = result_data[address]
|
||||||
if test.dtype == 'int':
|
if test.dtype == 'int':
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
from copapy import variable, Target, iif
|
from copapy import value, Target, iif
|
||||||
import pytest
|
import pytest
|
||||||
import copapy
|
import copapy
|
||||||
|
|
||||||
|
|
||||||
def test_compile():
|
def test_compile():
|
||||||
c_i = variable(9)
|
c_i = value(9)
|
||||||
c_f = variable(2.5)
|
c_f = value(2.5)
|
||||||
# c_b = variable(True)
|
# c_b = variable(True)
|
||||||
|
|
||||||
ret_test = (iif(c_f > 5, c_f, -1), iif(c_i > 5, c_f, 8.8), iif(c_i > 2, c_i, 1))
|
ret_test = (iif(c_f > 5, c_f, -1), iif(c_i > 5, c_f, 8.8), iif(c_i > 2, c_i, 1))
|
||||||
|
|
@ -19,7 +19,7 @@ def test_compile():
|
||||||
print('* finished')
|
print('* finished')
|
||||||
|
|
||||||
for test, ref in zip(ret_test, ret_ref):
|
for test, ref in zip(ret_test, ret_ref):
|
||||||
assert isinstance(test, copapy.variable)
|
assert isinstance(test, copapy.value)
|
||||||
val = tg.read_value(test)
|
val = tg.read_value(test)
|
||||||
print('+', val, ref, type(val), test.dtype)
|
print('+', val, ref, type(val), test.dtype)
|
||||||
#for t in (int, float, bool):
|
#for t in (int, float, bool):
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import pytest
|
||||||
|
|
||||||
def test_readme_example():
|
def test_readme_example():
|
||||||
# Define variables
|
# Define variables
|
||||||
a = cp.variable(0.25)
|
a = cp.value(0.25)
|
||||||
b = cp.variable(0.87)
|
b = cp.value(0.87)
|
||||||
|
|
||||||
# Define computations
|
# Define computations
|
||||||
c = a + b * 2.0
|
c = a + b * 2.0
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ target = cp.vector([0.7, 0.7])
|
||||||
alpha = 0.1
|
alpha = 0.1
|
||||||
|
|
||||||
|
|
||||||
def forward_kinematics(theta1: cp.variable[float] | float, theta2: cp.variable[float] | float) -> tuple[cp.vector[float], cp.vector[float]]:
|
def forward_kinematics(theta1: cp.value[float] | float, theta2: cp.value[float] | float) -> tuple[cp.vector[float], cp.vector[float]]:
|
||||||
"""Return positions of joint and end-effector."""
|
"""Return positions of joint and end-effector."""
|
||||||
joint = cp.vector([l1 * cp.cos(theta1), l1 * cp.sin(theta1)])
|
joint = cp.vector([l1 * cp.cos(theta1), l1 * cp.sin(theta1)])
|
||||||
end_effector = joint + cp.vector([l2 * cp.cos(theta1 + theta2),
|
end_effector = joint + cp.vector([l2 * cp.cos(theta1 + theta2),
|
||||||
|
|
@ -20,7 +20,7 @@ def forward_kinematics(theta1: cp.variable[float] | float, theta2: cp.variable[f
|
||||||
|
|
||||||
def test_two_arms():
|
def test_two_arms():
|
||||||
target_vec = cp.vector(target)
|
target_vec = cp.vector(target)
|
||||||
theta = cp.vector([cp.variable(0.0), cp.variable(0.0)])
|
theta = cp.vector([cp.value(0.0), cp.value(0.0)])
|
||||||
|
|
||||||
joint = cp.vector([0.0, 0.0])
|
joint = cp.vector([0.0, 0.0])
|
||||||
effector = cp.vector([0.0, 0.0])
|
effector = cp.vector([0.0, 0.0])
|
||||||
|
|
|
||||||
|
|
@ -5,38 +5,38 @@ from copapy import filters
|
||||||
|
|
||||||
def test_vectors_init():
|
def test_vectors_init():
|
||||||
tt1 = cp.vector(range(3)) + cp.vector([1.1, 2.2, 3.3])
|
tt1 = cp.vector(range(3)) + cp.vector([1.1, 2.2, 3.3])
|
||||||
tt2 = cp.vector([1.1, 2, cp.variable(5)]) + cp.vector(range(3))
|
tt2 = cp.vector([1.1, 2, cp.value(5)]) + cp.vector(range(3))
|
||||||
tt3 = (cp.vector(range(3)) + 5.6)
|
tt3 = (cp.vector(range(3)) + 5.6)
|
||||||
tt4 = cp.vector([1.1, 2, 3]) + cp.vector(cp.variable(v) for v in range(3))
|
tt4 = cp.vector([1.1, 2, 3]) + cp.vector(cp.value(v) for v in range(3))
|
||||||
tt5 = cp.vector([1, 2, 3]).dot(tt4)
|
tt5 = cp.vector([1, 2, 3]).dot(tt4)
|
||||||
|
|
||||||
print(tt1, tt2, tt3, tt4, tt5)
|
print(tt1, tt2, tt3, tt4, tt5)
|
||||||
|
|
||||||
|
|
||||||
def test_compiled_vectors():
|
def test_compiled_vectors():
|
||||||
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.variable(v) for v in range(3))
|
t1 = cp.vector([10, 11, 12]) + cp.vector(cp.value(v) for v in range(3))
|
||||||
t2 = t1.sum()
|
t2 = t1.sum()
|
||||||
|
|
||||||
t3 = cp.vector(cp.variable(1 / (v + 1)) for v in range(3))
|
t3 = cp.vector(cp.value(1 / (v + 1)) for v in range(3))
|
||||||
t4 = ((t3 * t1) * 2).sum()
|
t4 = ((t3 * t1) * 2).sum()
|
||||||
t5 = ((t3 * t1) * 2).magnitude()
|
t5 = ((t3 * t1) * 2).magnitude()
|
||||||
|
|
||||||
t6 = cp.angle_between(cp.vector([cp.variable(5.0), 0.0, 0.0]), cp.vector([5.0, 5.0, 0.0]))
|
t6 = cp.angle_between(cp.vector([cp.value(5.0), 0.0, 0.0]), cp.vector([5.0, 5.0, 0.0]))
|
||||||
|
|
||||||
tg = cp.Target()
|
tg = cp.Target()
|
||||||
tg.compile(t2, t4, t5, t6)
|
tg.compile(t2, t4, t5, t6)
|
||||||
tg.run()
|
tg.run()
|
||||||
|
|
||||||
assert isinstance(t2, cp.variable)
|
assert isinstance(t2, cp.value)
|
||||||
assert tg.read_value(t2) == 10 + 11 + 12 + 0 + 1 + 2
|
assert tg.read_value(t2) == 10 + 11 + 12 + 0 + 1 + 2
|
||||||
|
|
||||||
assert isinstance(t4, cp.variable)
|
assert isinstance(t4, cp.value)
|
||||||
assert tg.read_value(t4) == pytest.approx(((10/1*2) + (12/2*2) + (14/3*2)), 0.001) # pyright: ignore[reportUnknownMemberType]
|
assert tg.read_value(t4) == pytest.approx(((10/1*2) + (12/2*2) + (14/3*2)), 0.001) # pyright: ignore[reportUnknownMemberType]
|
||||||
|
|
||||||
assert isinstance(t5, cp.variable)
|
assert isinstance(t5, cp.value)
|
||||||
assert tg.read_value(t5) == pytest.approx(((10/1*2)**2 + (12/2*2)**2 + (14/3*2)**2) ** 0.5, 0.001) # pyright: ignore[reportUnknownMemberType]
|
assert tg.read_value(t5) == pytest.approx(((10/1*2)**2 + (12/2*2)**2 + (14/3*2)**2) ** 0.5, 0.001) # pyright: ignore[reportUnknownMemberType]
|
||||||
|
|
||||||
assert isinstance(t6, cp.variable)
|
assert isinstance(t6, cp.value)
|
||||||
assert tg.read_value(t6) == pytest.approx(math.pi / 4, 0.001), tg.read_value(t6) # pyright: ignore[reportUnknownMemberType]
|
assert tg.read_value(t6) == pytest.approx(math.pi / 4, 0.001), tg.read_value(t6) # pyright: ignore[reportUnknownMemberType]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ def test_non_compiled_vector_operations():
|
||||||
|
|
||||||
def test_sort_vector():
|
def test_sort_vector():
|
||||||
vlist = [50, 21, 20, 10, 22, 1, 80, 70, 90]
|
vlist = [50, 21, 20, 10, 22, 1, 80, 70, 90]
|
||||||
t1 = cp.vector(cp.variable(v) for v in vlist)
|
t1 = cp.vector(cp.value(v) for v in vlist)
|
||||||
#t1 = cp.vector(v for v in vlist)
|
#t1 = cp.vector(v for v in vlist)
|
||||||
|
|
||||||
t2 = filters.median(t1)
|
t2 = filters.median(t1)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from copapy import variable
|
from copapy import value
|
||||||
from copapy.backend import Write, compile_to_dag, stencil_db_from_package
|
from copapy.backend import Write, compile_to_dag, stencil_db_from_package
|
||||||
from copapy._binwrite import Command
|
from copapy._binwrite import Command
|
||||||
import copapy as cp
|
import copapy as cp
|
||||||
|
|
@ -6,7 +6,7 @@ import copapy as cp
|
||||||
|
|
||||||
def compile_to_x86_64() -> None:
|
def compile_to_x86_64() -> None:
|
||||||
"""Test compilation of a simple program for x86_64."""
|
"""Test compilation of a simple program for x86_64."""
|
||||||
c1 = variable(9.0)
|
c1 = value(9.0)
|
||||||
|
|
||||||
#ret = [c1 / 4, c1 / -4, c1 // 4, c1 // -4, (c1 * -1) // 4]
|
#ret = [c1 / 4, c1 / -4, c1 // 4, c1 // -4, (c1 * -1) // 4]
|
||||||
ret = [c1 // 3.3 + 5]
|
ret = [c1 // 3.3 + 5]
|
||||||
|
|
@ -29,14 +29,14 @@ def compile_to_x86_64() -> None:
|
||||||
|
|
||||||
def compile_to_x86() -> None:
|
def compile_to_x86() -> None:
|
||||||
"""Test compilation of a simple program for x86 32 bit."""
|
"""Test compilation of a simple program for x86 32 bit."""
|
||||||
c1 = variable(9.0)
|
c1 = value(9.0)
|
||||||
|
|
||||||
#ret = [c1 / 4, c1 / -4, c1 // 4, c1 // -4, (c1 * -1) // 4]
|
#ret = [c1 / 4, c1 / -4, c1 // 4, c1 // -4, (c1 * -1) // 4]
|
||||||
ret = [c1 // 3.3 + 5]
|
ret = [c1 // 3.3 + 5]
|
||||||
#ret = [cp.sqrt(c1)]
|
#ret = [cp.sqrt(c1)]
|
||||||
#c2 = cp._math.get_42()
|
#c2 = cp._math.get_42()
|
||||||
#ret = [c2]
|
#ret = [c2]
|
||||||
ret = [cp.sin(variable(2.5))]
|
ret = [cp.sin(value(2.5))]
|
||||||
|
|
||||||
out = [Write(r) for r in ret]
|
out = [Write(r) for r in ret]
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ def compile_to_x86() -> None:
|
||||||
|
|
||||||
def compile_to_aarch64() -> None:
|
def compile_to_aarch64() -> None:
|
||||||
"""Test compilation of a simple program for arm64."""
|
"""Test compilation of a simple program for arm64."""
|
||||||
c1 = variable(9.0)
|
c1 = value(9.0)
|
||||||
|
|
||||||
#ret = [c1 / 4, c1 / -4, c1 // 4, c1 // -4, (c1 * -1) // 4]
|
#ret = [c1 / 4, c1 / -4, c1 // 4, c1 // -4, (c1 * -1) // 4]
|
||||||
#ret = [cp.sin(c1), cp.sqrt(c1) + 5]
|
#ret = [cp.sin(c1), cp.sqrt(c1) + 5]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue