diff --git a/docs/basic-usage/compilation-modes.rst b/docs/basic-usage/compilation-modes.rst index 534ae4ab9..9a34531b4 100644 --- a/docs/basic-usage/compilation-modes.rst +++ b/docs/basic-usage/compilation-modes.rst @@ -33,36 +33,36 @@ during the call to :func:`~galois.GF`. The exponential and logarithm lookup tables map every finite field element to a power of the primitive element $\alpha$. -.. math:: - x = \alpha^i +$$x = \alpha^i$$ -.. math:: - \textrm{log}_{\alpha}(x) = i +$$\textrm{log}_{\alpha}(x) = i$$ With these lookup tables, many arithmetic operations are simplified. For instance, multiplication of two finite field elements is reduced to three lookups and one integer addition. -.. math:: - x \cdot y &= \alpha^m \cdot \alpha^n \\ - &= \alpha^{m + n} +$$ +x \cdot y +&= \alpha^m \cdot \alpha^n \\ +&= \alpha^{m + n} +$$ The `Zech logarithm `_ is defined below. A similar lookup table is created for it. -.. math:: - 1 + \alpha^i = \alpha^{Z(i)} +$$1 + \alpha^i = \alpha^{Z(i)}$$ -.. math:: - Z(i) = \textrm{log}_{\alpha}(1 + \alpha^i) +$$Z(i) = \textrm{log}_{\alpha}(1 + \alpha^i)$$ With Zech logarithms, addition of two finite field elements becomes three lookups, one integer addition, and one integer subtraction. -.. math:: - x + y &= \alpha^m + \alpha^n \\ - &= \alpha^m (1 + \alpha^{n - m}) \\ - &= \alpha^m \alpha^{Z(n - m)} \\ - &= \alpha^{m + Z(n - m)} +$$ +x + y +&= \alpha^m + \alpha^n \\ +&= \alpha^m (1 + \alpha^{n - m}) \\ +&= \alpha^m \alpha^{Z(n - m)} \\ +&= \alpha^{m + Z(n - m)} +$$ Finite fields with order less than $2^{20}$ use lookup tables by default. In the limited cases where explicit calculation is faster than table lookup, the explicit calculation is used. diff --git a/src/galois/_codes/_bch.py b/src/galois/_codes/_bch.py index f7249a2bd..4df4cffe7 100644 --- a/src/galois/_codes/_bch.py +++ b/src/galois/_codes/_bch.py @@ -41,9 +41,7 @@ class BCH(_CyclicCode): evaluated in $\mathrm{GF}(q^m)$. The element $\alpha$ is a primitive $n$-th root of unity in $\mathrm{GF}(q^m)$. - .. math:: - - g(x) = \textrm{LCM}(m_{\alpha^c}(x), \dots, m_{\alpha^{c+d-2}}(x)) + $$g(x) = \textrm{LCM}(m_{\alpha^c}(x), \dots, m_{\alpha^{c+d-2}}(x))$$ Examples: Construct a binary $\textrm{BCH}(15, 7)$ code. @@ -507,11 +505,9 @@ def decode( operation computes the remainder of $r(x)$ by $g(x)$ in the extension field $\mathrm{GF}(q^m)$. - .. math:: - \mathbf{s} = [r(\alpha^c),\ \dots,\ r(\alpha^{c+d-2})] \in \mathrm{GF}(q^m)^{d-1} + $$\mathbf{s} = [r(\alpha^c),\ \dots,\ r(\alpha^{c+d-2})] \in \mathrm{GF}(q^m)^{d-1}$$ - .. math:: - s(x) = r(x)\ \textrm{mod}\ g(x) \in \mathrm{GF}(q^m)[x] + $$s(x) = r(x)\ \textrm{mod}\ g(x) \in \mathrm{GF}(q^m)[x]$$ A syndrome of zeros indicates the received codeword is a valid codeword and there are no errors. If the syndrome is non-zero, the decoder will find an error-locator polynomial $\sigma(x)$ and the corresponding diff --git a/src/galois/_codes/_cyclic.py b/src/galois/_codes/_cyclic.py index bf2ac3c3c..a76281e91 100644 --- a/src/galois/_codes/_cyclic.py +++ b/src/galois/_codes/_cyclic.py @@ -61,30 +61,24 @@ def __init__( The message vector $\mathbf{m}$ is a member of $\mathrm{GF}(q)^k$. The corresponding message polynomial $m(x)$ is a degree-$k$ polynomial over $\mathrm{GF}(q)$. - .. math:: - \mathbf{m} = [m_{k-1},\ \dots,\ m_1,\ m_0] \in \mathrm{GF}(q)^k + $$\mathbf{m} = [m_{k-1},\ \dots,\ m_1,\ m_0] \in \mathrm{GF}(q)^k$$ - .. math:: - m(x) = m_{k-1} x^{k-1} + \dots + m_1 x + m_0 \in \mathrm{GF}(q)[x] + $$m(x) = m_{k-1} x^{k-1} + \dots + m_1 x + m_0 \in \mathrm{GF}(q)[x]$$ The codeword vector $\mathbf{c}$ is a member of $\mathrm{GF}(q)^n$. The corresponding codeword polynomial $c(x)$ is a degree-$n$ polynomial over $\mathrm{GF}(q)$. - .. math:: - \mathbf{c} = [c_{n-1},\ \dots,\ c_1,\ c_0] \in \mathrm{GF}(q)^n + $$\mathbf{c} = [c_{n-1},\ \dots,\ c_1,\ c_0] \in \mathrm{GF}(q)^n$$ - .. math:: - c(x) = c_{n-1} x^{n-1} + \dots + c_1 x + c_0 \in \mathrm{GF}(q)[x] + $$c(x) = c_{n-1} x^{n-1} + \dots + c_1 x + c_0 \in \mathrm{GF}(q)[x]$$ The codeword vector is computed by matrix multiplication of the message vector with the generator matrix. The equivalent polynomial operation is multiplication of the message polynomial with the generator polynomial. - .. math:: - \mathbf{c} = \mathbf{m} \mathbf{G} + $$\mathbf{c} = \mathbf{m} \mathbf{G}$$ - .. math:: - c(x) = m(x) g(x) + $$c(x) = m(x) g(x)$$ """, ) def encode(self, message: ArrayLike, output: Literal["codeword", "parity"] = "codeword") -> FieldArray: @@ -116,21 +110,17 @@ def decode( The message vector $\mathbf{m}$ is a member of $\mathrm{GF}(q)^k$. The corresponding message polynomial $m(x)$ is a degree-$k$ polynomial over $\mathrm{GF}(q)$. - .. math:: - \mathbf{m} = [m_{k-1},\ \dots,\ m_1,\ m_0] \in \mathrm{GF}(q)^k + $$\mathbf{m} = [m_{k-1},\ \dots,\ m_1,\ m_0] \in \mathrm{GF}(q)^k$$ - .. math:: - m(x) = m_{k-1} x^{k-1} + \dots + m_1 x + m_0 \in \mathrm{GF}(q)[x] + $$m(x) = m_{k-1} x^{k-1} + \dots + m_1 x + m_0 \in \mathrm{GF}(q)[x]$$ The codeword vector $\mathbf{c}$ is a member of $\mathrm{GF}(q)^n$. The corresponding codeword polynomial $c(x)$ is a degree-$n$ polynomial over $\mathrm{GF}(q)$. Each codeword polynomial $c(x)$ is divisible by the generator polynomial $g(x)$. - .. math:: - \mathbf{c} = [c_{n-1},\ \dots,\ c_1,\ c_0] \in \mathrm{GF}(q)^n + $$\mathbf{c} = [c_{n-1},\ \dots,\ c_1,\ c_0] \in \mathrm{GF}(q)^n$$ - .. math:: - c(x) = c_{n-1} x^{n-1} + \dots + c_1 x + c_0 \in \mathrm{GF}(q)[x] + $$c(x) = c_{n-1} x^{n-1} + \dots + c_1 x + c_0 \in \mathrm{GF}(q)[x]$$ """, ) def decode(self, codeword, output="message", errors=False): diff --git a/src/galois/_codes/_linear.py b/src/galois/_codes/_linear.py index eefa96ada..39b93bcd6 100644 --- a/src/galois/_codes/_linear.py +++ b/src/galois/_codes/_linear.py @@ -337,8 +337,7 @@ def t(self) -> int: Notes: The code can correct $t$ symbol errors in a codeword. - .. math:: - t = \bigg\lfloor \frac{d - 1}{2} \bigg\rfloor + $$t = \bigg\lfloor \frac{d - 1}{2} \bigg\rfloor$$ """ return (self.d - 1) // 2 diff --git a/src/galois/_codes/_reed_solomon.py b/src/galois/_codes/_reed_solomon.py index 4a73864dd..25740972d 100644 --- a/src/galois/_codes/_reed_solomon.py +++ b/src/galois/_codes/_reed_solomon.py @@ -37,9 +37,7 @@ class ReedSolomon(_CyclicCode): generator polynomial has $d-1$ roots $\alpha^c, \dots, \alpha^{c+d-2}$. The element $\alpha$ is a primitive $n$-th root of unity in $\mathrm{GF}(q)$. - .. math:: - - g(x) = (x - \alpha^c) \dots (x - \alpha^{c+d-2}) + $$g(x) = (x - \alpha^c) \dots (x - \alpha^{c+d-2})$$ Examples: Construct a $\textrm{RS}(15, 9)$ code. @@ -461,11 +459,9 @@ def decode( $\mathbf{r}$ at the roots $\alpha^c, \dots, \alpha^{c+d-2}$ of the generator polynomial $g(x)$. The equivalent polynomial operation computes the remainder of $r(x)$ by $g(x)$. - .. math:: - \mathbf{s} = [r(\alpha^c),\ \dots,\ r(\alpha^{c+d-2})] \in \mathrm{GF}(q)^{d-1} + $$\mathbf{s} = [r(\alpha^c),\ \dots,\ r(\alpha^{c+d-2})] \in \mathrm{GF}(q)^{d-1}$$ - .. math:: - s(x) = r(x)\ \textrm{mod}\ g(x) \in \mathrm{GF}(q)[x] + $$s(x) = r(x)\ \textrm{mod}\ g(x) \in \mathrm{GF}(q)[x]$$ A syndrome of zeros indicates the received codeword is a valid codeword and there are no errors. If the syndrome is non-zero, the decoder will find an error-locator polynomial $\sigma(x)$ and the corresponding diff --git a/src/galois/_fields/_array.py b/src/galois/_fields/_array.py index 79606364a..8b7bf5e5c 100644 --- a/src/galois/_fields/_array.py +++ b/src/galois/_fields/_array.py @@ -1474,8 +1474,7 @@ def field_trace(self) -> FieldArray: For finite fields, since $L$ is a Galois extension of $K$, the field trace of $x$ is defined as a sum of the Galois conjugates of $x$. - .. math:: - \mathrm{Tr}_{L / K}(x) = \sum_{i=0}^{m-1} x^{p^i} + $$\mathrm{Tr}_{L / K}(x) = \sum_{i=0}^{m-1} x^{p^i}$$ References: - https://en.wikipedia.org/wiki/Field_trace @@ -1520,8 +1519,7 @@ def field_norm(self) -> FieldArray: For finite fields, since $L$ is a Galois extension of $K$, the field norm of $x$ is defined as a product of the Galois conjugates of $x$. - .. math:: - \mathrm{N}_{L / K}(x) = \prod_{i=0}^{m-1} x^{p^i} = x^{(p^m - 1) / (p - 1)} + $$\mathrm{N}_{L / K}(x) = \prod_{i=0}^{m-1} x^{p^i} = x^{(p^m - 1) / (p - 1)}$$ References: - https://en.wikipedia.org/wiki/Field_norm diff --git a/src/galois/_lfsr.py b/src/galois/_lfsr.py index 142e659ad..9709204d2 100644 --- a/src/galois/_lfsr.py +++ b/src/galois/_lfsr.py @@ -183,17 +183,14 @@ class FLFSR(_LFSR): Notes: A Fibonacci LFSR is defined by its feedback polynomial $f(x)$. - .. math:: - f(x) = -c_{0}x^{n} - c_{1}x^{n-1} - \dots - c_{n-2}x^{2} - c_{n-1}x + 1 = x^n c(x^{-1}) + $$f(x) = -c_{0}x^{n} - c_{1}x^{n-1} - \dots - c_{n-2}x^{2} - c_{n-1}x + 1 = x^n c(x^{-1})$$ The feedback polynomial is the reciprocal of the characteristic polynomial $c(x)$ of the linear recurrent sequence $y$ produced by the Fibonacci LFSR. - .. math:: - c(x) = x^{n} - c_{n-1}x^{n-1} - c_{n-2}x^{n-2} - \dots - c_{1}x - c_{0} + $$c(x) = x^{n} - c_{n-1}x^{n-1} - c_{n-2}x^{n-2} - \dots - c_{1}x - c_{0}$$ - .. math:: - y_t = c_{n-1}y_{t-1} + c_{n-2}y_{t-2} + \dots + c_{1}y_{t-n+2} + c_{0}y_{t-n+1} + $$y_t = c_{n-1}y_{t-1} + c_{n-2}y_{t-2} + \dots + c_{1}y_{t-n+2} + c_{0}y_{t-n+1}$$ .. code-block:: text :caption: Fibonacci LFSR Configuration @@ -816,17 +813,14 @@ class GLFSR(_LFSR): Notes: A Galois LFSR is defined by its feedback polynomial $f(x)$. - .. math:: - f(x) = -c_{0}x^{n} - c_{1}x^{n-1} - \dots - c_{n-2}x^{2} - c_{n-1}x + 1 = x^n c(x^{-1}) + $$f(x) = -c_{0}x^{n} - c_{1}x^{n-1} - \dots - c_{n-2}x^{2} - c_{n-1}x + 1 = x^n c(x^{-1})$$ The feedback polynomial is the reciprocal of the characteristic polynomial $c(x)$ of the linear recurrent sequence $y$ produced by the Galois LFSR. - .. math:: - c(x) = x^{n} - c_{n-1}x^{n-1} - c_{n-2}x^{n-2} - \dots - c_{1}x - c_{0} + $$c(x) = x^{n} - c_{n-1}x^{n-1} - c_{n-2}x^{n-2} - \dots - c_{1}x - c_{0}$$ - .. math:: - y_t = c_{n-1}y_{t-1} + c_{n-2}y_{t-2} + \dots + c_{1}y_{t-n+2} + c_{0}y_{t-n+1} + $$y_t = c_{n-1}y_{t-1} + c_{n-2}y_{t-2} + \dots + c_{1}y_{t-n+2} + c_{0}y_{t-n+1}$$ .. code-block:: text :caption: Galois LFSR Configuration @@ -1460,11 +1454,9 @@ def berlekamp_massey(sequence, output="minimal"): The minimal polynomial is the characteristic polynomial $c(x)$ of minimal degree that produces the linear recurrent sequence $y$. - .. math:: - c(x) = x^{n} - c_{n-1}x^{n-1} - c_{n-2}x^{n-2} - \dots - c_{1}x - c_{0} + $$c(x) = x^{n} - c_{n-1}x^{n-1} - c_{n-2}x^{n-2} - \dots - c_{1}x - c_{0}$$ - .. math:: - y_t = c_{n-1}y_{t-1} + c_{n-2}y_{t-2} + \dots + c_{1}y_{t-n+2} + c_{0}y_{t-n+1} + $$y_t = c_{n-1}y_{t-1} + c_{n-2}y_{t-2} + \dots + c_{1}y_{t-n+2} + c_{0}y_{t-n+1}$$ For a linear sequence with order $n$, at least $2n$ output symbols are required to determine the minimal polynomial. diff --git a/src/galois/_modular.py b/src/galois/_modular.py index f292afd04..3f5fea4fa 100644 --- a/src/galois/_modular.py +++ b/src/galois/_modular.py @@ -81,8 +81,7 @@ def euler_phi(n: int) -> int: Notes: This function implements the Euler totient function - .. math:: - \phi(n) = n \prod_{p\ |\ n} \bigg(1 - \frac{1}{p}\bigg) = \prod_{i=1}^{k} p_i^{e_i-1} \big(p_i - 1\big) + $$\phi(n) = n \prod_{p\ |\ n} \bigg(1 - \frac{1}{p}\bigg) = \prod_{i=1}^{k} p_i^{e_i-1} \big(p_i - 1\big)$$ for prime $p$ and the prime factorization $n = p_1^{e_1} \dots p_k^{e_k}$. @@ -743,8 +742,7 @@ def is_primitive_root(g: int, n: int) -> bool: Alternatively said, $g$ is a primitive root modulo $n$ if and only if $g$ is a generator of the multiplicative group of integers modulo $n$, - .. math:: - (\mathbb{Z}/n\mathbb{Z}){^\times} = \{1, g, g^2, \dots, g^{\phi(n)-1}\} + $$(\mathbb{Z}/n\mathbb{Z}){^\times} = \{1, g, g^2, \dots, g^{\phi(n)-1}\}$$ where $\phi(n)$ is order of the group. diff --git a/src/galois/_ntt.py b/src/galois/_ntt.py index cd18b71e3..03d112e26 100644 --- a/src/galois/_ntt.py +++ b/src/galois/_ntt.py @@ -53,8 +53,7 @@ def ntt( The $k$-th value of the $N$-point NTT $X = \mathrm{NTT}(x)$ is - .. math:: - X_k = \sum_{j=0}^{N-1} x_j \omega_N^{jk} , + $$X_k = \sum_{j=0}^{N-1} x_j \omega_N^{jk} ,$$ with all arithmetic performed in $\mathrm{GF}(p)$. @@ -163,8 +162,7 @@ def intt( The $j$-th value of the scaled $N$-point INTT $x = \mathrm{INTT}(X)$ is - .. math:: - x_j = \frac{1}{N} \sum_{k=0}^{N-1} X_k \omega_N^{-kj} , + $$x_j = \frac{1}{N} \sum_{k=0}^{N-1} X_k \omega_N^{-kj} ,$$ with all arithmetic performed in $\mathrm{GF}(p)$. The scaled INTT has the property that $x = \mathrm{INTT}(\mathrm{NTT}(x))$. diff --git a/src/galois/_polymorphic.py b/src/galois/_polymorphic.py index 00434027c..041acccb6 100644 --- a/src/galois/_polymorphic.py +++ b/src/galois/_polymorphic.py @@ -409,11 +409,12 @@ def crt(remainders, moduli): Notes: This function implements the Chinese Remainder Theorem. - .. math:: - x &\equiv a_1\ (\textrm{mod}\ m_1) \\ - x &\equiv a_2\ (\textrm{mod}\ m_2) \\ - x &\equiv \ldots \\ - x &\equiv a_n\ (\textrm{mod}\ m_n) + $$ + x &\equiv a_1\ (\textrm{mod}\ m_1) \\ + x &\equiv a_2\ (\textrm{mod}\ m_2) \\ + x &\equiv \ldots \\ + x &\equiv a_n\ (\textrm{mod}\ m_n) + $$ References: - Section 14.5 from https://cacr.uwaterloo.ca/hac/about/chap14.pdf @@ -684,16 +685,14 @@ def is_square_free(value): A square-free integer $n$ is divisible by no perfect squares. As a consequence, the prime factorization of a square-free integer $n$ is - .. math:: - n = \prod_{i=1}^{k} p_i^{e_i} = \prod_{i=1}^{k} p_i . + $$n = \prod_{i=1}^{k} p_i^{e_i} = \prod_{i=1}^{k} p_i .$$ .. md-tab-item:: Polynomials A square-free polynomial $f(x)$ has no irreducible factors with multiplicity greater than one. Therefore, its canonical factorization is - .. math:: - f(x) = \prod_{i=1}^{k} g_i(x)^{e_i} = \prod_{i=1}^{k} g_i(x) . + $$f(x) = \prod_{i=1}^{k} g_i(x)^{e_i} = \prod_{i=1}^{k} g_i(x) .$$ This test is also available in :func:`Poly.is_square_free`. diff --git a/src/galois/_polys/_factor.py b/src/galois/_polys/_factor.py index d709f628b..27da3c5fd 100644 --- a/src/galois/_polys/_factor.py +++ b/src/galois/_polys/_factor.py @@ -27,8 +27,7 @@ def is_square_free(f) -> bool: A square-free polynomial $f(x)$ has no irreducible factors with multiplicity greater than one. Therefore, its canonical factorization is - .. math:: - f(x) = \prod_{i=1}^{k} g_i(x)^{e_i} = \prod_{i=1}^{k} g_i(x) . + $$f(x) = \prod_{i=1}^{k} g_i(x)^{e_i} = \prod_{i=1}^{k} g_i(x) .$$ Examples: Generate irreducible polynomials over $\mathrm{GF}(3)$. @@ -74,8 +73,7 @@ def square_free_factors(f: Poly) -> tuple[list[Poly], list[int]]: The Square-Free Factorization algorithm factors $f(x)$ into a product of $m$ square-free polynomials $h_j(x)$ with multiplicity $j$. - .. math:: - f(x) = \prod_{j=1}^{m} h_j(x)^j + $$f(x) = \prod_{j=1}^{m} h_j(x)^j$$ Some $h_j(x) = 1$, but those polynomials are not returned by this function. @@ -175,17 +173,17 @@ def distinct_degree_factors(f: Poly) -> tuple[list[Poly], list[int]]: $d$ into a product of $d$ polynomials $f_i(x)$, where $f_i(x)$ is the product of all irreducible factors of $f(x)$ with degree $i$. - .. math:: - f(x) = \prod_{i=1}^{d} f_i(x) + $$f(x) = \prod_{i=1}^{d} f_i(x)$$ For example, suppose $f(x) = x(x + 1)(x^2 + x + 1)(x^3 + x + 1)(x^3 + x^2 + 1)$ over $\mathrm{GF}(2)$, then the distinct-degree factorization is - .. math:: - f_1(x) &= x(x + 1) = x^2 + x \\ - f_2(x) &= x^2 + x + 1 \\ - f_3(x) &= (x^3 + x + 1)(x^3 + x^2 + 1) = x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 \\ - f_i(x) &= 1\ \textrm{for}\ i = 4, \dots, 10. + $$ + f_1(x) &= x(x + 1) = x^2 + x \\ + f_2(x) &= x^2 + x + 1 \\ + f_3(x) &= (x^3 + x + 1)(x^3 + x^2 + 1) = x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 \\ + f_i(x) &= 1\ \textrm{for}\ i = 4, \dots, 10. + $$ Some $f_i(x) = 1$, but those polynomials are not returned by this function. In this example, the function returns $\{f_1(x), f_2(x), f_3(x)\}$ and $\{1, 2, 3\}$. diff --git a/src/galois/_polys/_lagrange.py b/src/galois/_polys/_lagrange.py index 0a06d1185..0e4695134 100644 --- a/src/galois/_polys/_lagrange.py +++ b/src/galois/_polys/_lagrange.py @@ -31,11 +31,9 @@ def lagrange_poly(x: Array, y: Array) -> Poly: Notes: The Lagrange interpolating polynomial is defined as - .. math:: - L(x) = \sum_{j=0}^{k-1} y_j \ell_j(x) + $$L(x) = \sum_{j=0}^{k-1} y_j \ell_j(x)$$ - .. math:: - \ell_j(x) = \prod_{\substack{0 \le m < k \\ m \ne j}} \frac{x - x_m}{x_j - x_m} . + $$\ell_j(x) = \prod_{\substack{0 \le m < k \\ m \ne j}} \frac{x - x_m}{x_j - x_m} .$$ It is the polynomial of minimal degree that satisfies $L(x_i) = y_i$. diff --git a/src/galois/_polys/_poly.py b/src/galois/_polys/_poly.py index 7b88231a7..833a6b11a 100644 --- a/src/galois/_polys/_poly.py +++ b/src/galois/_polys/_poly.py @@ -543,9 +543,11 @@ def Roots( The polynomial $f(x)$ with $k$ roots $\{r_1, r_2, \dots, r_k\}$ with multiplicities $\{m_1, m_2, \dots, m_k\}$ is - .. math:: - f(x) &= (x - r_1)^{m_1} (x - r_2)^{m_2} \dots (x - r_k)^{m_k} \\ - &= a_d x^d + a_{d-1} x^{d-1} + \dots + a_1 x + a_0 + $$ + f(x) + &= (x - r_1)^{m_1} (x - r_2)^{m_2} \dots (x - r_k)^{m_k} \\ + &= a_d x^d + a_{d-1} x^{d-1} + \dots + a_1 x + a_0 + $$ with degree $d = \sum_{i=1}^{k} m_i$. @@ -669,8 +671,7 @@ def reverse(self) -> Poly: For a polynomial $f(x) = a_d x^d + a_{d-1} x^{d-1} + \dots + a_1 x + a_0$ with degree $d$, the $d$-th reversal is equivalent to reversing the coefficients. - .. math:: - \textrm{rev}_d f(x) = x^d f(x^{-1}) = a_0 x^d + a_{1} x^{d-1} + \dots + a_{d-1} x + a_d + $$\textrm{rev}_d f(x) = x^d f(x^{-1}) = a_0 x^d + a_{1} x^{d-1} + \dots + a_{d-1} x + a_d$$ Examples: .. ipython:: python @@ -707,13 +708,11 @@ def roots(self, multiplicity=False): This implementation uses Chien's search to find the roots $\{r_1, r_2, \dots, r_k\}$ of the degree-$d$ polynomial - .. math:: - f(x) = a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0, + $$f(x) = a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0,$$ where $k \le d$. Then, $f(x)$ can be factored as - .. math:: - f(x) = (x - r_1)^{m_1} (x - r_2)^{m_2} \dots (x - r_k)^{m_k}, + $$f(x) = (x - r_1)^{m_1} (x - r_2)^{m_2} \dots (x - r_k)^{m_k},$$ where $m_i$ is the multiplicity of root $r_i$ and $d = \sum_{i=1}^{k} m_i$. @@ -726,18 +725,22 @@ def roots(self, multiplicity=False): $\alpha$. The following equations calculate $f(\alpha^i)$, where $\alpha^i$ is a root of $f(x)$ if $f(\alpha^i) = 0$. - .. math:: - f(\alpha^i) &= a_{d}(\alpha^i)^{d} + \dots + a_1(\alpha^i) + a_0 \\ - &\overset{\Delta}{=} \lambda_{i,d} + \dots + \lambda_{i,1} + \lambda_{i,0} \\ - &= \sum_{j=0}^{d} \lambda_{i,j} + $$ + f(\alpha^i) + &= a_{d}(\alpha^i)^{d} + \dots + a_1(\alpha^i) + a_0 \\ + &\overset{\Delta}{=} \lambda_{i,d} + \dots + \lambda_{i,1} + \lambda_{i,0} \\ + &= \sum_{j=0}^{d} \lambda_{i,j} + $$ The next power of $\alpha$ can be easily calculated from the previous calculation. - .. math:: - f(\alpha^{i+1}) &= a_{d}(\alpha^{i+1})^{d} + \dots + a_1(\alpha^{i+1}) + a_0 \\ - &= a_{d}(\alpha^i)^{d}\alpha^d + \dots + a_1(\alpha^i)\alpha + a_0 \\ - &= \lambda_{i,d}\alpha^d + \dots + \lambda_{i,1}\alpha + \lambda_{i,0} \\ - &= \sum_{j=0}^{d} \lambda_{i,j}\alpha^j + $$ + f(\alpha^{i+1}) + &= a_{d}(\alpha^{i+1})^{d} + \dots + a_1(\alpha^{i+1}) + a_0 \\ + &= a_{d}(\alpha^i)^{d}\alpha^d + \dots + a_1(\alpha^i)\alpha + a_0 \\ + &= \lambda_{i,d}\alpha^d + \dots + \lambda_{i,1}\alpha + \lambda_{i,0} \\ + &= \sum_{j=0}^{d} \lambda_{i,j}\alpha^j + $$ Examples: Find the roots of a polynomial over $\mathrm{GF}(2)$. @@ -811,13 +814,11 @@ def derivative(self, k: int = 1) -> Poly: Notes: For the polynomial - .. math:: - f(x) = a_d x^d + a_{d-1} x^{d-1} + \dots + a_1 x + a_0 + $$f(x) = a_d x^d + a_{d-1} x^{d-1} + \dots + a_1 x + a_0$$ the first formal derivative is defined as - .. math:: - f'(x) = (d) \cdot a_{d} x^{d-1} + (d-1) \cdot a_{d-1} x^{d-2} + \dots + (2) \cdot a_{2} x + a_1 + $$f'(x) = (d) \cdot a_{d} x^{d-1} + (d-1) \cdot a_{d-1} x^{d-2} + \dots + (2) \cdot a_{2} x + a_1$$ where $\cdot$ represents scalar multiplication (repeated addition), not finite field multiplication. The exponent that is "brought down" and multiplied by the coefficient is an integer, not a finite field diff --git a/src/galois/_prime.py b/src/galois/_prime.py index 71b3d6a19..359aa94f3 100644 --- a/src/galois/_prime.py +++ b/src/galois/_prime.py @@ -1351,8 +1351,7 @@ def divisor_sigma(n: int, k: int = 1) -> int: Notes: This function implements the $\sigma_k(n)$ function. It is defined as: - .. math:: - \sigma_k(n) = \sum_{d\ |\ n} d^k + $$\sigma_k(n) = \sum_{d\ \mid\ n} d^k$$ Examples: .. ipython:: python