diff --git a/src/copapy/filters.py b/src/copapy/filters.py new file mode 100644 index 0000000..8639b1f --- /dev/null +++ b/src/copapy/filters.py @@ -0,0 +1,64 @@ +from . import variable, vector +from ._basic_types import iif, unifloat, TNum +from typing import Any, Iterable + + +def homogenize_vector(input_values: Iterable[TNum | variable[TNum]]) -> Iterable[TNum] | Iterable[variable[TNum]]: + input_list = list(input_values) + if any(isinstance(val, variable) for val in input_list): + return (v if isinstance(v, variable) else variable(v) for v in input_list) + else: + return (v for v in input_list if not isinstance(v, variable)) + + +def _inv_argsort(input_vector: vector[TNum]) -> vector[int]: + positions = (sum((v1 > v2) for v2 in input_vector) for v1 in input_vector) + return vector(positions) + + +def argsort(input_vector: vector[TNum]) -> vector[int]: + """ + Perform an indirect sort. It returns an array of indices that index data + in sorted order. + + Args: + input_vector: The input vector containing numerical values. + + Returns: + Index array. + """ + return _inv_argsort(_inv_argsort(input_vector)) + + +def median(input_vector: vector[TNum]) -> TNum | variable[TNum]: + """ + Applies a median filter to the input vector and returns the median as a unifloat. + + Args: + input_vector: The input vector containing numerical values. + + Returns: + The median value of the input vector. + """ + vec = input_vector + ret = vec[0] + for v1 in vec: + n2 = len(vec) // 2 + 1 + lt = sum(v1 < v2 for v2 in vec) + gt = sum(v1 > v2 for v2 in vec) + ret = iif((lt < n2) & (gt < n2), v1, ret) + + return ret + + +def mean(input_vector: vector[Any]) -> unifloat: + """ + Applies a mean filter to the input vector and returns the mean as a unifloat. + + Args: + input_vector (vector): The input vector containing numerical values. + + Returns: + unifloat: The mean value of the input vector. + """ + return input_vector.sum() / len(input_vector) \ No newline at end of file diff --git a/tests/test_vector.py b/tests/test_vector.py index db44649..c893f6b 100644 --- a/tests/test_vector.py +++ b/tests/test_vector.py @@ -1,7 +1,7 @@ import math import copapy as cp import pytest - +from copapy import filters def test_vectors_init(): tt1 = cp.vector(range(3)) + cp.vector([1.1, 2.2, 3.3]) @@ -95,12 +95,27 @@ def test_non_compiled_vector_operations(): assert rotated.values[2] == pytest.approx(3.0, abs=1e-6) # pyright: ignore[reportUnknownMemberType] -if __name__ == "__main__": - test_vectors_init() - test_compiled_vectors() - test_vector_operations() - print('Finished!') +def test_sort_vector(): + vlist = [50, 21, 20, 10, 22, 1, 80, 70, 90] + t1 = cp.vector(cp.variable(v) for v in vlist) + #t1 = cp.vector(v for v in vlist) + + t2 = filters.median(t1) + + tg = cp.Target() + tg.compile(t2) + tg.run() + + result = tg.read_value(t2) + + ref = sorted(vlist)[len(vlist) // 2] + print(sorted(vlist)) + + assert ref == result + if __name__ == "__main__": - test_compiled_vectors() + #test_vectors_init() + #test_compiled_vectors() + test_sort_vector() print('Finished!')