Skip to content

Chebyshev polynomial

beignet.add_chebyshev_polynomial

add_chebyshev_polynomial(input, other)

Returns the sum of two polynomials.

Parameters:

Name Type Description Default
input Tensor

Polynomial coefficients.

required
other Tensor

Polynomial coefficients.

required

Returns:

Name Type Description
output Tensor

Polynomial coefficients.

Source code in src/beignet/_add_chebyshev_polynomial.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def add_chebyshev_polynomial(input: Tensor, other: Tensor) -> Tensor:
    r"""
    Returns the sum of two polynomials.

    Parameters
    ----------
    input : Tensor
        Polynomial coefficients.

    other : Tensor
        Polynomial coefficients.

    Returns
    -------
    output : Tensor
        Polynomial coefficients.
    """
    input = torch.atleast_1d(input)
    other = torch.atleast_1d(other)

    dtype = torch.promote_types(input.dtype, other.dtype)

    input = input.to(dtype)
    other = other.to(dtype)

    if input.shape[0] > other.shape[0]:
        output = torch.concatenate(
            [
                other,
                torch.zeros(
                    input.shape[0] - other.shape[0],
                    dtype=other.dtype,
                ),
            ],
        )

        output = input + output
    else:
        output = torch.concatenate(
            [
                input,
                torch.zeros(
                    other.shape[0] - input.shape[0],
                    dtype=input.dtype,
                ),
            ]
        )

        output = other + output

    return output

beignet.chebyshev_extrema

chebyshev_extrema(input)
Source code in src/beignet/_chebyshev_extrema.py
 7
 8
 9
10
11
def chebyshev_extrema(input: int) -> Tensor:
    if input < 2:
        raise ValueError

    return torch.cos(torch.linspace(-math.pi, 0, input))

beignet.chebyshev_gauss_quadrature

chebyshev_gauss_quadrature(degree)
Source code in src/beignet/_chebyshev_gauss_quadrature.py
 8
 9
10
11
12
13
14
15
16
def chebyshev_gauss_quadrature(degree: int) -> Tuple[Tensor, Tensor]:
    if not degree > 0:
        raise ValueError

    output = torch.cos(torch.arange(1, 2 * degree, 2) / (2 * degree) * math.pi)

    weight = torch.ones(degree) * (math.pi / degree)

    return output, weight

beignet.chebyshev_interpolation

chebyshev_interpolation(func, degree, *args)
Source code in src/beignet/_chebyshev_interpolation.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def chebyshev_interpolation(
    func: Callable[[Tensor, ...], Tensor],
    degree: int,
    *args,
):
    if degree < 0:
        raise ValueError

    order = degree + 1

    if order < 1:
        raise ValueError

    zeros = torch.arange(-order + 1, order + 1, 2)

    zeros = torch.sin(zeros * 0.5 * math.pi / order)

    vandermonde = torch.empty([degree + 1, *zeros.shape], dtype=zeros.dtype)

    vandermonde[0] = torch.ones_like(zeros)

    if degree > 0:
        vandermonde[1] = zeros

        for i in range(2, degree + 1):
            v = vandermonde[i - 1] * zeros * 2.0 - vandermonde[i - 2]

            vandermonde[i] = v

    vandermonde = torch.moveaxis(vandermonde, 0, -1)

    output = vandermonde.T @ func(zeros, *args)

    output[0] = output[0] / order

    output[1:] = output[1:] / (order * 0.5)

    return output

beignet.chebyshev_polynomial_companion

chebyshev_polynomial_companion(input)
Source code in src/beignet/_chebyshev_polynomial_companion.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def chebyshev_polynomial_companion(input: Tensor) -> Tensor:
    input = torch.atleast_1d(input)

    if input.shape[0] < 2:
        raise ValueError

    if input.shape[0] == 2:
        return torch.tensor([[-input[0] / input[1]]])

    n = input.shape[0] - 1

    output = torch.zeros(
        [
            n,
            n,
        ],
        dtype=input.dtype,
    )

    scale = torch.ones([n])

    scale[1:] = math.sqrt(0.5)

    shape = output.shape

    output = torch.reshape(output, [-1])

    x = torch.full([n - 1], 1 / 2)

    x[0] = math.sqrt(0.5)

    output[1 :: n + 1] = x
    output[n :: n + 1] = x

    output = torch.reshape(output, shape)

    output[:, -1] = (
        output[:, -1] + -(input[:-1] / input[-1]) * (scale / scale[-1]) * 0.5
    )

    return output

beignet.chebyshev_polynomial_domain module-attribute

chebyshev_polynomial_domain = tensor([-1.0, 1.0])

beignet.chebyshev_polynomial_from_roots

chebyshev_polynomial_from_roots(input)
Source code in src/beignet/_chebyshev_polynomial_from_roots.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def chebyshev_polynomial_from_roots(input: Tensor) -> Tensor:
    f = linear_chebyshev_polynomial
    g = multiply_chebyshev_polynomial
    if math.prod(input.shape) == 0:
        return torch.ones([1])

    input, _ = torch.sort(input)

    ys = []

    for x in input:
        a = torch.zeros(input.shape[0] + 1, dtype=x.dtype)
        b = f(-x, 1)

        a = torch.atleast_1d(a)
        b = torch.atleast_1d(b)

        dtype = torch.promote_types(a.dtype, b.dtype)

        a = a.to(dtype)
        b = b.to(dtype)

        if a.shape[0] > b.shape[0]:
            y = torch.concatenate(
                [
                    b,
                    torch.zeros(
                        a.shape[0] - b.shape[0],
                        dtype=b.dtype,
                    ),
                ],
            )

            y = a + y
        else:
            y = torch.concatenate(
                [
                    a,
                    torch.zeros(
                        b.shape[0] - a.shape[0],
                        dtype=a.dtype,
                    ),
                ]
            )

            y = b + y

        ys = [*ys, y]

    p = torch.stack(ys)

    m = p.shape[0]

    x = m, p

    while x[0] > 1:
        m, r = divmod(x[0], 2)

        z = x[1]

        previous = torch.zeros([len(p), input.shape[0] + 1])

        y = previous

        for i in range(0, m):
            y[i] = g(z[i], z[i + m])[: input.shape[0] + 1]

        previous = y

        if r:
            previous[0] = g(previous[0], z[2 * m])[: input.shape[0] + 1]

        x = m, previous

    _, output = x

    return output[0]

beignet.chebyshev_polynomial_one module-attribute

chebyshev_polynomial_one = tensor([1.0])

beignet.chebyshev_polynomial_power

chebyshev_polynomial_power(input, exponent, maximum_exponent=16.0)
Source code in src/beignet/_chebyshev_polynomial_power.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def chebyshev_polynomial_power(
    input: Tensor,
    exponent: float | Tensor,
    maximum_exponent: float | Tensor = 16.0,
) -> Tensor:
    input = torch.atleast_1d(input)

    _exponent = int(exponent)

    if _exponent != exponent or _exponent < 0:
        raise ValueError

    if maximum_exponent is not None and _exponent > maximum_exponent:
        raise ValueError

    match _exponent:
        case 0:
            output = torch.tensor([1.0], dtype=input.dtype)
        case 1:
            output = input
        case _:
            output = torch.zeros(input.shape[0] * exponent, dtype=input.dtype)

            output = add_chebyshev_polynomial(output, input)

            index1 = math.prod(input.shape)
            output2 = torch.zeros(2 * index1 - 1, dtype=input.dtype)
            output2[index1 - 1 :] = input / 2.0
            output2 = torch.flip(output2, dims=[0]) + output2
            zs = output2

            index = math.prod(output.shape)
            output1 = torch.zeros(2 * index - 1, dtype=output.dtype)
            output1[index - 1 :] = output / 2.0
            output1 = torch.flip(output1, dims=[0]) + output1
            output = output1

            for _ in range(2, _exponent + 1):
                output = convolve(output, zs, mode="same")

            n = (math.prod(output.shape) + 1) // 2
            c = output[n - 1 :]
            c[1:n] = c[1:n] * 2.0
            output = c

    return output

beignet.chebyshev_polynomial_roots

chebyshev_polynomial_roots(input)
Source code in src/beignet/_chebyshev_polynomial_roots.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def chebyshev_polynomial_roots(input: Tensor) -> Tensor:
    input = torch.atleast_1d(input)

    if input.shape[0] <= 1:
        return torch.tensor([], dtype=input.dtype)

    if input.shape[0] == 2:
        return torch.tensor([-input[0] / input[1]])

    output = chebyshev_polynomial_companion(input)

    output = torch.flip(output, dims=[0])
    output = torch.flip(output, dims=[1])

    output = torch.linalg.eigvals(output)

    output, _ = torch.sort(output.real)

    return output

beignet.chebyshev_polynomial_to_polynomial

chebyshev_polynomial_to_polynomial(input)
Source code in src/beignet/_chebyshev_polynomial_to_polynomial.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def chebyshev_polynomial_to_polynomial(input: Tensor) -> Tensor:
    input = torch.atleast_1d(input)

    n = input.shape[0]

    if n < 3:
        return input

    c0 = torch.zeros_like(input)
    c0[0] = input[-2]

    c1 = torch.zeros_like(input)
    c1[0] = input[-1]

    for index in range(0, n - 2):
        i1 = n - 1 - index

        tmp = c0

        c0 = subtract_polynomial(input[i1 - 2], c1)

        c1 = add_polynomial(tmp, multiply_polynomial_by_x(c1, "same") * 2)

    output = multiply_polynomial_by_x(c1, "same")

    output = add_polynomial(c0, output)

    return output

beignet.chebyshev_polynomial_vandermonde

chebyshev_polynomial_vandermonde(x, degree)
Source code in src/beignet/_chebyshev_polynomial_vandermonde.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def chebyshev_polynomial_vandermonde(
    x: Tensor,
    degree: Tensor,
) -> Tensor:
    if degree < 0:
        raise ValueError

    x = torch.atleast_1d(x)
    dims = (degree + 1,) + x.shape
    dtyp = torch.promote_types(x.dtype, torch.tensor(0.0).dtype)
    x = x.to(dtyp)
    v = torch.empty(dims, dtype=dtyp)

    v[0] = torch.ones_like(x)

    if degree > 0:
        v[1] = x

        x2 = 2 * x

        for index in range(2, degree + 1):
            v[index] = v[index - 1] * x2 - v[index - 2]

    return torch.moveaxis(v, 0, -1)

beignet.chebyshev_polynomial_vandermonde_2d

chebyshev_polynomial_vandermonde_2d(x, y, degree)
Source code in src/beignet/_chebyshev_polynomial_vandermonde_2d.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
def chebyshev_polynomial_vandermonde_2d(
    x: Tensor,
    y: Tensor,
    degree: Tensor,
) -> Tensor:
    functions = (
        chebyshev_polynomial_vandermonde,
        chebyshev_polynomial_vandermonde,
    )

    n = len(functions)

    if n != len([x, y]):
        raise ValueError

    if n != len(degree):
        raise ValueError

    if n == 0:
        raise ValueError

    matrices = []

    for i in range(n):
        matrix = functions[i]((x, y)[i], degree[i])

        matrices = [
            *matrices,
            matrix[(..., *tuple(slice(None) if j == i else None for j in range(n)))],
        ]

    vandermonde = functools.reduce(
        operator.mul,
        matrices,
    )

    return torch.reshape(
        vandermonde,
        [*vandermonde.shape[: -len(degree)], -1],
    )

beignet.chebyshev_polynomial_vandermonde_3d

chebyshev_polynomial_vandermonde_3d(x, y, z, degree)
Source code in src/beignet/_chebyshev_polynomial_vandermonde_3d.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def chebyshev_polynomial_vandermonde_3d(
    x: Tensor,
    y: Tensor,
    z: Tensor,
    degree: Tensor,
) -> Tensor:
    functions = (
        chebyshev_polynomial_vandermonde,
        chebyshev_polynomial_vandermonde,
        chebyshev_polynomial_vandermonde,
    )

    n = len(functions)

    if n != len([x, y, z]):
        raise ValueError

    if n != len(degree):
        raise ValueError

    if n == 0:
        raise ValueError

    matrices = []

    for i in range(n):
        matrix = functions[i]((x, y, z)[i], degree[i])

        matrices = [
            *matrices,
            matrix[(..., *tuple(slice(None) if j == i else None for j in range(n)))],
        ]

    vandermonde = functools.reduce(
        operator.mul,
        matrices,
    )

    return torch.reshape(
        vandermonde,
        [*vandermonde.shape[: -len(degree)], -1],
    )

beignet.chebyshev_polynomial_weight

chebyshev_polynomial_weight(input)
Source code in src/beignet/_chebyshev_polynomial_weight.py
5
6
def chebyshev_polynomial_weight(input: Tensor) -> Tensor:
    return 1.0 / (torch.sqrt(1.0 + input) * torch.sqrt(1.0 - input))

beignet.chebyshev_polynomial_x module-attribute

chebyshev_polynomial_x = tensor([0.0, 1.0])

beignet.chebyshev_polynomial_zero module-attribute

chebyshev_polynomial_zero = tensor([0.0])

beignet.chebyshev_zeros

chebyshev_zeros(input)
Source code in src/beignet/_chebyshev_zeros.py
 7
 8
 9
10
11
def chebyshev_zeros(input: int) -> Tensor:
    if input < 1:
        raise ValueError

    return torch.sin(0.5 * math.pi / input * torch.arange(-input + 1, input + 1, 2))

beignet.differentiate_chebyshev_polynomial

differentiate_chebyshev_polynomial(input, order=1, scale=1, axis=0)

Returns the derivative of a polynomial.

Parameters:

Name Type Description Default
input Tensor

Polynomial coefficients.

required
order Tensor
1
scale Tensor
1
dim int
0

Returns:

Name Type Description
output Tensor

Polynomial coefficients of the derivative.

Source code in src/beignet/_differentiate_chebyshev_polynomial.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def differentiate_chebyshev_polynomial(
    input: Tensor,
    order=1,
    scale=1,
    axis=0,
) -> Tensor:
    r"""
    Returns the derivative of a polynomial.

    Parameters
    ----------
    input : Tensor
        Polynomial coefficients.

    order : Tensor, optional

    scale : Tensor, optional

    dim : int, default=0

    Returns
    -------
    output : Tensor
        Polynomial coefficients of the derivative.
    """
    if order < 0:
        raise ValueError

    input = torch.atleast_1d(input)

    if order == 0:
        return input

    output = torch.moveaxis(input, axis, 0)

    n = output.shape[0]

    if order >= n:
        output = torch.zeros_like(output[:1])
    else:
        for _ in range(order):
            n = n - 1

            output = output * scale

            derivative = torch.empty((n,) + output.shape[1:], dtype=output.dtype)

            for i in range(0, n - 2):
                j = n - i

                derivative[j - 1] = (2 * j) * output[j]

                output[j - 2] += (j * output[j]) / (j - 2)

            if n > 1:
                derivative[1] = 4 * output[2]

            derivative[0] = output[1]

    return torch.moveaxis(output, 0, axis)

beignet.divide_chebyshev_polynomial

divide_chebyshev_polynomial(input, other)

Returns the quotient and remainder of two polynomials.

Parameters:

Name Type Description Default
input Tensor

Polynomial coefficients.

required
other Tensor

Polynomial coefficients.

required

Returns:

Name Type Description
output Tuple[Tensor, Tensor]

Polynomial coefficients of the quotient and remainder.

Source code in src/beignet/_divide_chebyshev_polynomial.py
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def divide_chebyshev_polynomial(
    input: Tensor,
    other: Tensor,
) -> Tuple[Tensor, Tensor]:
    r"""
    Returns the quotient and remainder of two polynomials.

    Parameters
    ----------
    input : Tensor
        Polynomial coefficients.

    other : Tensor
        Polynomial coefficients.

    Returns
    -------
    output : Tuple[Tensor, Tensor]
        Polynomial coefficients of the quotient and remainder.
    """
    input = torch.atleast_1d(input)
    other = torch.atleast_1d(other)

    dtype = torch.promote_types(input.dtype, other.dtype)

    input = input.to(dtype)
    other = other.to(dtype)

    m = input.shape[0]
    n = other.shape[0]

    if m < n:
        return torch.zeros_like(input[:1]), input

    if n == 1:
        return input / other[-1], torch.zeros_like(input[:1])

    def f(x: Tensor) -> Tensor:
        indicies = torch.flip(x, [0])

        indicies = torch.nonzero(indicies, as_tuple=False)

        if indicies.shape[0] > 1:
            indicies = indicies[:1]

        if indicies.shape[0] < 1:
            indicies = torch.concatenate(
                [
                    indicies,
                    torch.full(
                        [
                            1 - indicies.shape[0],
                            indicies.shape[1],
                        ],
                        0,
                    ),
                ],
                0,
            )

        return x.shape[0] - 1 - indicies[0][0]

    quotient = torch.zeros(m - n + 1, dtype=input.dtype)

    ridx = input.shape[0] - 1

    size = m - f(other) - 1

    y = torch.zeros(m + n + 1, dtype=input.dtype)

    y[size] = 1.0

    x = quotient, input, y, ridx

    for index in range(0, size):
        quotient, remainder, y2, ridx1 = x

        j = size - index

        p = multiply_chebyshev_polynomial(y2, other)

        pidx = f(p)

        t = remainder[ridx1] / p[pidx]

        remainder_modified = remainder.clone()
        remainder_modified[ridx1] = 0.0

        a = remainder_modified

        p_modified = p.clone()
        p_modified[pidx] = 0.0

        b = t * p_modified

        a = torch.atleast_1d(a)
        b = torch.atleast_1d(b)

        dtype = torch.promote_types(a.dtype, b.dtype)

        a = a.to(dtype)
        b = b.to(dtype)

        if a.shape[0] > b.shape[0]:
            output = -b

            output = torch.concatenate(
                [
                    output,
                    torch.zeros(
                        a.shape[0] - b.shape[0],
                        dtype=b.dtype,
                    ),
                ],
            )
            output = a + output
        else:
            output = -b

            output = torch.concatenate(
                [
                    output[: a.shape[0]] + a,
                    output[a.shape[0] :],
                ],
            )

        remainder = output

        remainder = remainder[: remainder.shape[0]]

        quotient[j] = t

        ridx1 = ridx1 - 1

        y2 = torch.roll(y2, -1)

        x = quotient, remainder, y2, ridx1

    quotient, remainder, _, _ = x

    return quotient, remainder

beignet.evaluate_chebyshev_polynomial

evaluate_chebyshev_polynomial(input, coefficients, tensor=True)
Source code in src/beignet/_evaluate_chebyshev_polynomial.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def evaluate_chebyshev_polynomial(
    input: Tensor,
    coefficients: Tensor,
    tensor: bool = True,
) -> Tensor:
    coefficients = torch.atleast_1d(coefficients)

    if tensor:
        coefficients = torch.reshape(
            coefficients,
            coefficients.shape + (1,) * input.ndim,
        )

    match coefficients.shape[0]:
        case 1:
            a = coefficients[0]
            b = 0.0
        case 2:
            a = coefficients[0]
            b = coefficients[1]
        case _:
            a = coefficients[-2] * torch.ones_like(input)
            b = coefficients[-1] * torch.ones_like(input)

            for i in range(3, coefficients.shape[0] + 1):
                previous = a

                a = coefficients[-i] - b
                b = previous + b * 2.0 * input

    return a + b * input

beignet.evaluate_chebyshev_polynomial_2d

evaluate_chebyshev_polynomial_2d(x, y, coefficients)
Source code in src/beignet/_evaluate_chebyshev_polynomial_2d.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def evaluate_chebyshev_polynomial_2d(
    x: Tensor,
    y: Tensor,
    coefficients: Tensor,
) -> Tensor:
    points = [x, y]

    if not all(a.shape == points[0].shape for a in points[1:]):
        match len(points):
            case 2:
                raise ValueError
            case 3:
                raise ValueError
            case _:
                raise ValueError

    points = iter(points)

    output = evaluate_chebyshev_polynomial(
        next(points),
        coefficients,
    )

    for x in points:
        output = evaluate_chebyshev_polynomial(
            x,
            output,
            tensor=False,
        )

    return output

beignet.evaluate_chebyshev_polynomial_3d

evaluate_chebyshev_polynomial_3d(x, y, z, coefficients)
Source code in src/beignet/_evaluate_chebyshev_polynomial_3d.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def evaluate_chebyshev_polynomial_3d(
    x: Tensor,
    y: Tensor,
    z: Tensor,
    coefficients: Tensor,
) -> Tensor:
    points = [x, y, z]

    if not all(a.shape == points[0].shape for a in points[1:]):
        match len(points):
            case 2:
                raise ValueError
            case 3:
                raise ValueError
            case _:
                raise ValueError

    points = iter(points)

    output = evaluate_chebyshev_polynomial(
        next(points),
        coefficients,
    )

    for x in points:
        output = evaluate_chebyshev_polynomial(
            x,
            output,
            tensor=False,
        )

    return output

beignet.evaluate_chebyshev_polynomial_cartesian_2d

evaluate_chebyshev_polynomial_cartesian_2d(x, y, c)
Source code in src/beignet/_evaluate_chebyshev_polynomial_cartesian_2d.py
 6
 7
 8
 9
10
11
12
13
def evaluate_chebyshev_polynomial_cartesian_2d(
    x: Tensor,
    y: Tensor,
    c: Tensor,
) -> Tensor:
    for arg in [x, y]:
        c = evaluate_chebyshev_polynomial(arg, c)
    return c

beignet.evaluate_chebyshev_polynomial_cartesian_3d

evaluate_chebyshev_polynomial_cartesian_3d(x, y, z, c)
Source code in src/beignet/_evaluate_chebyshev_polynomial_cartesian_3d.py
 6
 7
 8
 9
10
11
12
13
14
def evaluate_chebyshev_polynomial_cartesian_3d(
    x: Tensor,
    y: Tensor,
    z: Tensor,
    c: Tensor,
) -> Tensor:
    for arg in [x, y, z]:
        c = evaluate_chebyshev_polynomial(arg, c)
    return c

beignet.fit_chebyshev_polynomial

fit_chebyshev_polynomial(input, other, degree, relative_condition=None, full=False, weight=None)
Source code in src/beignet/_fit_chebyshev_polynomial.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
def fit_chebyshev_polynomial(
    input: Tensor,
    other: Tensor,
    degree: Tensor | int,
    relative_condition: float | None = None,
    full: bool = False,
    weight: Tensor | None = None,
):
    func = chebyshev_polynomial_vandermonde
    input = torch.tensor(input)
    other = torch.tensor(other)
    degree = torch.tensor(degree)
    if degree.ndim > 1:
        raise TypeError
    # if deg.dtype.kind not in "iu":
    #     raise TypeError
    if math.prod(degree.shape) == 0:
        raise TypeError
    if degree.min() < 0:
        raise ValueError
    if input.ndim != 1:
        raise TypeError
    if input.size == 0:
        raise TypeError
    if other.ndim < 1 or other.ndim > 2:
        raise TypeError
    if len(input) != len(other):
        raise TypeError
    if degree.ndim == 0:
        lmax = int(degree)
        van = func(input, lmax)
    else:
        degree, _ = torch.sort(degree)
        lmax = int(degree[-1])
        van = func(input, lmax)[:, degree]
    # set up the least squares matrices in transposed form
    lhs = van.T
    rhs = other.T
    if weight is not None:
        if weight.ndim != 1:
            raise TypeError("expected 1D vector for w")

        if len(input) != len(weight):
            raise TypeError("expected x and w to have same length")

        # apply weights. Don't use inplace operations as they
        # can cause problems with NA.
        lhs = lhs * weight
        rhs = rhs * weight
    # set rcond
    if relative_condition is None:
        relative_condition = len(input) * torch.finfo(input.dtype).eps
    # Determine the norms of the design matrix columns.
    if torch.is_complex(lhs):
        scl = torch.sqrt((torch.square(lhs.real) + torch.square(lhs.imag)).sum(1))
    else:
        scl = torch.sqrt(torch.square(lhs).sum(1))
    scl = torch.where(scl == 0, 1, scl)
    # Solve the least squares problem.
    c, resids, rank, s = torch.linalg.lstsq(lhs.T / scl, rhs.T, relative_condition)
    c = (c.T / scl).T
    # Expand c to include non-fitted coefficients which are set to zero
    if degree.ndim > 0:
        if c.ndim == 2:
            cc = torch.zeros((lmax + 1, c.shape[1]), dtype=c.dtype)
        else:
            cc = torch.zeros(lmax + 1, dtype=c.dtype)

        cc[degree] = c

        c = cc
    if full:
        result = c, [resids, rank, s, relative_condition]
    else:
        result = c
    return result

beignet.integrate_chebyshev_polynomial

integrate_chebyshev_polynomial(input, order=1, k=None, lower_bound=0, scale=1, axis=0)
Source code in src/beignet/_integrate_chebyshev_polynomial.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def integrate_chebyshev_polynomial(
    input: Tensor,
    order=1,
    k=None,
    lower_bound=0,
    scale=1,
    axis=0,
) -> Tensor:
    if k is None:
        k = []

    input = torch.atleast_1d(input)

    lower_bound = torch.tensor(lower_bound)

    scale = torch.tensor(scale)

    if not numpy.iterable(k):
        k = [k]

    if len(k) > order:
        raise ValueError

    if lower_bound.ndim != 0:
        raise ValueError

    if scale.ndim != 0:
        raise ValueError

    if order == 0:
        return input

    input = torch.moveaxis(input, axis, 0)

    k = torch.tensor([*k] + [0.0] * (order - len(k)))

    k = torch.atleast_1d(k)

    for i in range(order):
        n = input.shape[0]

        input = input * scale

        tmp = torch.empty([n + 1, *input.shape[1:]])

        tmp[0] = input[0] * 0
        tmp[1] = input[0]

        if n > 1:
            tmp[2] = input[1] / 4

        if n < 2:
            j = torch.tensor([], dtype=torch.int32)
        else:
            j = torch.arange(2, n)

        tmp[j + 1] = (input[j].T / (2 * (j + 1))).T
        tmp[j - 1] = tmp[j - 1] + -(input[j] / (2 * (j - 1)))

        tmp[0] = tmp[0] + (k[i] - evaluate_chebyshev_polynomial(lower_bound, tmp))

        input = tmp

    input = torch.moveaxis(input, 0, axis)

    return input

beignet.linear_chebyshev_polynomial

linear_chebyshev_polynomial(input, other)
Source code in src/beignet/_linear_chebyshev_polynomial.py
5
6
def linear_chebyshev_polynomial(input: float, other: float) -> Tensor:
    return torch.tensor([input, other])

beignet.multiply_chebyshev_polynomial

multiply_chebyshev_polynomial(input, other, mode='full')

Returns the product of two polynomials.

Parameters:

Name Type Description Default
input Tensor

Polynomial coefficients.

required
other Tensor

Polynomial coefficients.

required

Returns:

Name Type Description
output Tensor

Polynomial coefficients of the product.

Source code in src/beignet/_multiply_chebyshev_polynomial.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def multiply_chebyshev_polynomial(
    input: Tensor,
    other: Tensor,
    mode: Literal["full", "same", "valid"] = "full",
) -> Tensor:
    r"""
    Returns the product of two polynomials.

    Parameters
    ----------
    input : Tensor
        Polynomial coefficients.

    other : Tensor
        Polynomial coefficients.

    Returns
    -------
    output : Tensor
        Polynomial coefficients of the product.
    """
    input = torch.atleast_1d(input)
    other = torch.atleast_1d(other)

    dtype = torch.promote_types(input.dtype, other.dtype)

    input = input.to(dtype)
    other = other.to(dtype)

    index = math.prod(input.shape)
    output1 = torch.zeros(2 * index - 1, dtype=input.dtype)
    output1[index - 1 :] = input / 2.0
    output1 = torch.flip(output1, dims=[0]) + output1
    a = output1

    index1 = math.prod(other.shape)
    output2 = torch.zeros(2 * index1 - 1, dtype=other.dtype)
    output2[index1 - 1 :] = other / 2.0
    output2 = torch.flip(output2, dims=[0]) + output2
    b = output2

    output = convolve(a, b, mode=mode)

    n = (math.prod(output.shape) + 1) // 2
    c = output[n - 1 :]
    c[1:n] = c[1:n] * 2.0
    output = c

    if mode == "same":
        output = output[: max(input.shape[0], other.shape[0])]

    return output

beignet.multiply_chebyshev_polynomial_by_x

multiply_chebyshev_polynomial_by_x(input, mode='full')
Source code in src/beignet/_multiply_chebyshev_polynomial_by_x.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def multiply_chebyshev_polynomial_by_x(
    input: Tensor,
    mode: Literal["full", "same", "valid"] = "full",
) -> Tensor:
    input = torch.atleast_1d(input)

    output = torch.zeros(input.shape[0] + 1, dtype=input.dtype)

    output[1] = input[0]

    if input.shape[0] > 1:
        output[2:] = input[1:] / 2

        output[0:-2] = output[0:-2] + input[1:] / 2

    if mode == "same":
        output = output[: input.shape[0]]

    return output

beignet.subtract_chebyshev_polynomial

subtract_chebyshev_polynomial(input, other)

Returns the difference of two polynomials.

Parameters:

Name Type Description Default
input Tensor

Polynomial coefficients.

required
other Tensor

Polynomial coefficients.

required

Returns:

Name Type Description
output Tensor

Polynomial coefficients of the difference.

Source code in src/beignet/_subtract_chebyshev_polynomial.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def subtract_chebyshev_polynomial(input: Tensor, other: Tensor) -> Tensor:
    r"""
    Returns the difference of two polynomials.

    Parameters
    ----------
    input : Tensor
        Polynomial coefficients.

    other : Tensor
        Polynomial coefficients.

    Returns
    -------
    output : Tensor
        Polynomial coefficients of the difference.
    """
    input = torch.atleast_1d(input)
    other = torch.atleast_1d(other)

    dtype = torch.promote_types(input.dtype, other.dtype)

    input = input.to(dtype)
    other = other.to(dtype)

    if input.shape[0] > other.shape[0]:
        output = -other

        output = torch.concatenate(
            [
                output,
                torch.zeros(
                    input.shape[0] - other.shape[0],
                    dtype=other.dtype,
                ),
            ],
        )
        output = input + output
    else:
        output = -other

        output = torch.concatenate(
            [
                output[: input.shape[0]] + input,
                output[input.shape[0] :],
            ],
        )

    return output

beignet.trim_chebyshev_polynomial_coefficients

trim_chebyshev_polynomial_coefficients(input, tol=0.0)
Source code in src/beignet/_trim_chebyshev_polynomial_coefficients.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def trim_chebyshev_polynomial_coefficients(
    input: Tensor,
    tol: float = 0.0,
) -> Tensor:
    if tol < 0:
        raise ValueError

    input = torch.atleast_1d(input)

    indices = torch.nonzero(torch.abs(input) > tol)

    if indices.shape[0] == 0:
        output = input[:1] * 0
    else:
        output = input[: indices[-1] + 1]

    return output