Skip to content

Legendre polynomial

beignet.add_legendre_polynomial

add_legendre_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_legendre_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_legendre_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.differentiate_legendre_polynomial

differentiate_legendre_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_legendre_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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def differentiate_legendre_polynomial(
    input,
    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

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

    n = input.shape[0]

    if order >= n:
        input = torch.zeros_like(input[:1])
    else:
        for _ in range(order):
            n = n - 1
            input *= scale
            der = torch.empty((n,) + input.shape[1:], dtype=input.dtype)

            def body(k, der_c, n=n):
                j = n - k

                der, c = der_c

                der[j - 1] = (2 * j - 1) * c[j]

                c[j - 2] += c[j]

                return der, c

            b = n - 2

            x = (der, input)

            y = x

            for index in range(0, b):
                y = body(index, y)

            der, input = y

            if n > 1:
                der[1] = 3 * input[2]

            der[0] = input[1]

            input = der

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

    return input

beignet.divide_legendre_polynomial

divide_legendre_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_legendre_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_legendre_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_legendre_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_legendre_polynomial

evaluate_legendre_polynomial(input, coefficients, tensor=True)
Source code in src/beignet/_evaluate_legendre_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
def evaluate_legendre_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 _:
            size = coefficients.shape[0]

            a = coefficients[-2] * torch.ones_like(input)
            b = coefficients[-1] * torch.ones_like(input)

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

                size = size - 1

                a = coefficients[-index] - (b * (size - 1.0)) / size

                b = previous + (b * input * (2.0 * size - 1.0)) / size

    return a + b * input

beignet.evaluate_legendre_polynomial_2d

evaluate_legendre_polynomial_2d(x, y, coefficients)
Source code in src/beignet/_evaluate_legendre_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_legendre_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_legendre_polynomial(
        next(points),
        coefficients,
    )

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

    return output

beignet.evaluate_legendre_polynomial_3d

evaluate_legendre_polynomial_3d(x, y, z, coefficients)
Source code in src/beignet/_evaluate_legendre_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_legendre_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_legendre_polynomial(
        next(points),
        coefficients,
    )

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

    return output

beignet.evaluate_legendre_polynomial_cartesian_2d

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

beignet.evaluate_legendre_polynomial_cartesian_3d

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

beignet.fit_legendre_polynomial

fit_legendre_polynomial(input, other, degree, relative_condition=None, full=False, weight=None)
Source code in src/beignet/_fit_legendre_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
def fit_legendre_polynomial(
    input: Tensor,
    other: Tensor,
    degree: Tensor | int,
    relative_condition: float | None = None,
    full: bool = False,
    weight: Tensor | None = None,
):
    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 = legendre_polynomial_vandermonde(input, lmax)
    else:
        degree, _ = torch.sort(degree)
        lmax = int(degree[-1])
        van = legendre_polynomial_vandermonde(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_legendre_polynomial

integrate_legendre_polynomial(input, order=1, k=None, lower_bound=0, scale=1, axis=0)
Source code in src/beignet/_integrate_legendre_polynomial.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def integrate_legendre_polynomial(
    input,
    order=1,
    k=None,
    lower_bound=0,
    scale=1,
    axis=0,
):
    if k is None:
        k = []

    input = torch.atleast_1d(input)

    lbnd, scl = map(torch.tensor, (lower_bound, scale))

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

    if len(k) > order:
        raise ValueError("Too many integration constants")

    if lbnd.ndim != 0:
        raise ValueError("lbnd must be a scalar.")

    if scl.ndim != 0:
        raise ValueError("scl must be a scalar.")

    if order == 0:
        return input

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

    k = torch.tensor(list(k) + [0] * (order - len(k)))
    k = torch.atleast_1d(k)

    for i in range(order):
        n = len(output)
        output *= scl
        tmp = torch.empty((n + 1,) + output.shape[1:], dtype=output.dtype)
        tmp[0] = output[0] * 0
        tmp[1] = output[0]
        if n > 1:
            tmp[2] = output[1] / 3

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

        t = (output[j].T / (2 * j + 1)).T
        tmp[j + 1] = t
        tmp[j - 1] += -t
        legval_value = evaluate_legendre_polynomial(lbnd, tmp)
        tmp[0] += k[i] - legval_value
        output = tmp

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

    return output

beignet.legendre_polynomial_companion

legendre_polynomial_companion(input)
Source code in src/beignet/_legendre_polynomial_companion.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
def legendre_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 = 1.0 / torch.sqrt(2 * torch.arange(n) + 1)

    shape = output.shape

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

    output[1 :: n + 1] = torch.arange(1, n) * scale[: n - 1] * scale[1:n]

    output[n :: n + 1] = torch.arange(1, n) * scale[: n - 1] * scale[1:n]

    output = torch.reshape(output, shape)

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

    return output

beignet.legendre_polynomial_domain module-attribute

legendre_polynomial_domain = tensor([-1.0, 1.0])

beignet.legendre_polynomial_from_roots

legendre_polynomial_from_roots(input)
Source code in src/beignet/_legendre_polynomial_from_roots.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
def legendre_polynomial_from_roots(input):
    f = linear_legendre_polynomial
    g = multiply_legendre_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.legendre_polynomial_one module-attribute

legendre_polynomial_one = tensor([1.0])

beignet.legendre_polynomial_power

legendre_polynomial_power(input, exponent, maximum_exponent=16.0)
Source code in src/beignet/_legendre_polynomial_power.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def legendre_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], dtype=input.dtype)
        case 1:
            output = input
        case _:
            output = torch.zeros(input.shape[0] * exponent, dtype=input.dtype)

            input = torch.atleast_1d(input)
            output = torch.atleast_1d(output)

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

            input = input.to(dtype)
            output = output.to(dtype)

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

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

                output = input + output

            for _ in range(2, _exponent + 1):
                output = multiply_legendre_polynomial(output, input, mode="same")
    return output

beignet.legendre_polynomial_roots

legendre_polynomial_roots(input)
Source code in src/beignet/_legendre_polynomial_roots.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def legendre_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 = legendre_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.legendre_polynomial_to_polynomial

legendre_polynomial_to_polynomial(input)
Source code in src/beignet/_legendre_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
37
38
39
40
41
42
43
44
45
46
47
def legendre_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]

    def body(k, c0c1):
        i = n - 1 - k

        c0, c1 = c0c1

        tmp = c0

        c0 = subtract_polynomial(input[i - 2], c1 * (i - 1) / i)

        c1 = add_polynomial(tmp, multiply_polynomial_by_x(c1, "same") * (2 * i - 1) / i)

        return c0, c1

    x = (c0, c1)

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

    c0, c1 = x

    output = multiply_polynomial_by_x(c1, "same")

    output = add_polynomial(c0, output)

    return output

beignet.legendre_polynomial_vandermonde

legendre_polynomial_vandermonde(x, degree)
Source code in src/beignet/_legendre_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
29
30
def legendre_polynomial_vandermonde(x: Tensor, degree: Tensor) -> Tensor:
    if degree < 0:
        raise ValueError

    x = torch.tensor(x)
    x = torch.atleast_1d(x)

    dims = (degree + 1,) + x.shape

    dtype = torch.promote_types(x.dtype, torch.tensor(0.0).dtype)

    x = x.to(dtype)

    v = torch.empty(dims, dtype=dtype)

    v[0] = torch.ones_like(x)

    if degree > 0:
        v[1] = x

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

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

beignet.legendre_polynomial_vandermonde_2d

legendre_polynomial_vandermonde_2d(x, y, degree)
Source code in src/beignet/_legendre_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 legendre_polynomial_vandermonde_2d(
    x: Tensor,
    y: Tensor,
    degree: Tensor,
) -> Tensor:
    functions = (
        legendre_polynomial_vandermonde,
        legendre_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.legendre_polynomial_vandermonde_3d

legendre_polynomial_vandermonde_3d(x, y, z, degree)
Source code in src/beignet/_legendre_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 legendre_polynomial_vandermonde_3d(
    x: Tensor,
    y: Tensor,
    z: Tensor,
    degree: Tensor,
) -> Tensor:
    functions = (
        legendre_polynomial_vandermonde,
        legendre_polynomial_vandermonde,
        legendre_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.legendre_polynomial_weight

legendre_polynomial_weight(x)
Source code in src/beignet/_legendre_polynomial_weight.py
5
6
def legendre_polynomial_weight(x: Tensor) -> Tensor:
    return torch.ones_like(x)

beignet.legendre_polynomial_x module-attribute

legendre_polynomial_x = tensor([0.0, 1.0])

beignet.legendre_polynomial_zero module-attribute

legendre_polynomial_zero = tensor([0.0])

beignet.linear_legendre_polynomial

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

beignet.multiply_legendre_polynomial

multiply_legendre_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_legendre_polynomial.py
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
def multiply_legendre_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)

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

    if m > n:
        x, y = other, input
    else:
        x, y = input, other

    match x.shape[0]:
        case 1:
            a = add_legendre_polynomial(torch.zeros(m + n - 1), x[0] * y)
            b = torch.zeros(m + n - 1)
        case 2:
            a = add_legendre_polynomial(torch.zeros(m + n - 1), x[0] * y)
            b = add_legendre_polynomial(torch.zeros(m + n - 1), x[1] * y)
        case _:
            size = x.shape[0]

            a = add_legendre_polynomial(torch.zeros(m + n - 1), x[-2] * y)
            b = add_legendre_polynomial(torch.zeros(m + n - 1), x[-1] * y)

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

                size = size - 1

                a = subtract_legendre_polynomial(
                    x[-index] * y, (b * (size - 1.0)) / size
                )

                b = add_legendre_polynomial(
                    previous,
                    (multiply_legendre_polynomial_by_x(b, "same") * (2.0 * size - 1.0))
                    / size,
                )

    output = add_legendre_polynomial(a, multiply_legendre_polynomial_by_x(b, "same"))

    if mode == "same":
        output = output[: max(m, n)]

    return output

beignet.multiply_legendre_polynomial_by_x

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

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

    for index in range(1, input.shape[0]):
        output[index + 1] = (input[index] * (index + 1)) / (index + index + 1)
        output[index - 1] = output[index - 1] + (input[index] * (index + 0)) / (
            index + index + 1
        )

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

    return output

beignet.subtract_legendre_polynomial

subtract_legendre_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_legendre_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_legendre_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_legendre_polynomial_coefficients

trim_legendre_polynomial_coefficients(input, tol=0.0)
Source code in src/beignet/_trim_legendre_polynomial_coefficients.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def trim_legendre_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