Skip to content

Commit

Permalink
Built site for gh-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
nessan committed Jul 25, 2024
1 parent 20cb8bf commit a34263f
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .nojekyll
Original file line number Diff line number Diff line change
@@ -1 +1 @@
db7ab86e
0f37c3a0
41 changes: 25 additions & 16 deletions content/notes/danilevsky.html
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ <h3 class="anchored" data-anchor-id="the-algorithm">The Algorithm</h3>
1 &amp; \text { for } j = k-1
\end{cases}
\end{aligned}
\]</span> That last step puts row <span class="math inline">\(k\)</span> of <span class="math inline">\(A\)</span> into companion matrix formthe later rows of <span class="math inline">\(A\)</span> are already there.</p>
\]</span> That last step puts row <span class="math inline">\(k\)</span> of <span class="math inline">\(A\)</span> into companion matrix formthe later rows of <span class="math inline">\(A\)</span> are already there.</p>
<p>.. If <span class="math inline">\(k &gt; 1\)</span>, then <span class="math inline">\(k \leftarrow k-1\)</span>, and we go back to step 1. Otherwise, we are finished.</p>
<p>. If <span class="math inline">\(a_{kk-1} = 0\)</span> even after trying the search in step 2 then we cannot perform step 3. + The current <span class="math inline">\(A\)</span> matrix must then have the following form: + <span class="math display">\[
A =
Expand Down Expand Up @@ -845,7 +845,7 @@ <h3 class="anchored" data-anchor-id="the-algorithm">The Algorithm</h3>
<h2 class="anchored" data-anchor-id="danilevsky-for-bit-matrices">Danilevsky for Bit-Matrices</h2>
<p>In the case of bit-matrices, or in more formal math-speak, matrices with elements in <span class="math inline">\(\FF\)</span>, the input matrix <span class="math inline">\(A\)</span> is all zeros or ones. Moreover, the usual addition and multiplication operators are performed modulo 2 so everything remains in the limited set <span class="math inline">\(\{0,1\}\)</span>. In <span class="math inline">\(\mathbb{F_2}\)</span> we can replace addition with the logical XOR operator and multiplication with the logical AND operator.</p>
<p>Note that in <span class="math inline">\(\mathbb{F_2}\)</span> we have <span class="math inline">\(1+1 = 2 \rightarrow 0\)</span> so the additive inverse of 1 is 1. And of course as usual, the additive inverse of 0 is 0. This means that in <span class="math inline">\(\mathbb{F_2}\)</span> negation is a no-op and any term like <span class="math inline">\(-b\)</span> can just be replaced with <span class="math inline">\(b\)</span>.</p>
<p>We always have <span class="math inline">\(1 * 1 = 1\)</span> so the multiplicative inverse of <span class="math inline">\(1\)</span> is just <span class="math inline">\(1\)</span>. Also just like <span class="math inline">\(\mathbb{R}\)</span>, the element <span class="math inline">\(0\)</span> has no multiplicative inverse in <span class="math inline">\(\mathbb{F_2}\)</span> eitheryou still cannot divide by zero. This means that if <span class="math inline">\(a, b \in \mathbb{F_2}\)</span> then a term like <span class="math inline">\(a/b\)</span> makes no sense if <span class="math inline">\(b=0\)</span> but otherwise <span class="math inline">\(a/b = a\)</span>.</p>
<p>We always have <span class="math inline">\(1 * 1 = 1\)</span> so the multiplicative inverse of <span class="math inline">\(1\)</span> is just <span class="math inline">\(1\)</span>. Also just like <span class="math inline">\(\mathbb{R}\)</span>, the element <span class="math inline">\(0\)</span> has no multiplicative inverse in <span class="math inline">\(\mathbb{F_2}\)</span> eitheryou still cannot divide by zero. This means that if <span class="math inline">\(a, b \in \mathbb{F_2}\)</span> then a term like <span class="math inline">\(a/b\)</span> makes no sense if <span class="math inline">\(b=0\)</span> but otherwise <span class="math inline">\(a/b = a\)</span>.</p>
<p>Let’s reconsider that very first step we took above to move our matrix <span class="math inline">\(A\)</span> closer to Frobenius form. That involved finding a matrix <span class="math inline">\(M\)</span> such that <span class="math inline">\(B = A \cdot M\)</span> had its final row in the required format.</p>
<p>Taking into account that now all the matrices are boolean and assuming that <span class="math inline">\(a_{nn-1} = 1\)</span> then the appropriate <span class="math inline">\(M\)</span> is:</p>
<p><span class="math display">\[
Expand All @@ -865,18 +865,22 @@ <h2 class="anchored" data-anchor-id="danilevsky-for-bit-matrices">Danilevsky for
<p>The full algorithm for matrices over <span class="math inline">\(\mathbb{R}\)</span> also works for matrices over <span class="math inline">\(\mathbb{F_2}\)</span>. As before, it proceeds in a sequence of steps that move <span class="math inline">\(A\)</span> closer to companion/Frobenius matrix form at the end of each one.</p>
<section id="the-algorithm-1" class="level3">
<h3 class="anchored" data-anchor-id="the-algorithm-1">The Algorithm</h3>
<p>. Initialize a counter <span class="math inline">\(k\)</span> to <span class="math inline">\(n\)</span> and <span class="math inline">\(A\)</span> to the input matrix.</p>
<p>. If <span class="math inline">\(a_{kk-1} = 0\)</span> look for an earlier element in the same row that is 1. That is, look for <span class="math inline">\(j &lt; k-1\)</span> where <span class="math inline">\(a_{kj} = 1\)</span>. + If we are successful then swap both the <em>rows and columns</em> <span class="math inline">\(j\)</span> and <span class="math inline">\(k-1\)</span> of <span class="math inline">\(A\)</span>. + Row and column swaps like that are permutation transformations and those preserve the eigen-structure.</p>
<p>. If by now <span class="math inline">\(a_{kk-1} = 1\)</span>:</p>
<p>.. Capture the elements from row <span class="math inline">\(k\)</span> of the matrix <span class="math inline">\(A\)</span> by setting <span class="math inline">\(m_ = \text{row}_k(A)\)</span>. + Note that by assumption <span class="math inline">\(m_{k-1} = a_{kk-1} = 1\)</span>.</p>
<p>.. Compute the elements of <span class="math inline">\(B\)</span> for rows <span class="math inline">\(i = 1, ..., k-1\)</span> as follows: + <span class="math display">\[
<ol type="1">
<li><p>Initialize a counter <span class="math inline">\(k\)</span> to <span class="math inline">\(n\)</span> and <span class="math inline">\(A\)</span> to the input matrix.</p></li>
<li><p>If <span class="math inline">\(a_{kk-1} = 0\)</span> look for an earlier element in the same row that is 1. That is, look for an index <span class="math inline">\(j &lt; k-1\)</span> such that <span class="math inline">\(a_{kj} = 1\)</span>. If found then swap <em>both</em> the rows and the columns <span class="math inline">\(j\)</span> and <span class="math inline">\(k-1\)</span> of <span class="math inline">\(A\)</span>. These swaps are permutation transformations that preserve the eigen-structure.</p></li>
<li><p>If after step 2 we have <span class="math inline">\(a_{kk-1} = 1\)</span>:</p>
<ul>
<li><p>Capture the elements from row <span class="math inline">\(k\)</span> of the matrix <span class="math inline">\(A\)</span> by setting <span class="math display">\[
m = \text{row}_k(A).
\]</span> Note that by assumption <span class="math inline">\(m_{k-1} = a_{kk-1} = 1\)</span>.</p></li>
<li><p>Compute the elements of <span class="math inline">\(B\)</span> for rows <span class="math inline">\(i = 1, ..., k-1\)</span> as follows <span class="math display">\[
b_{ij} =
\begin{cases}
a_{ij} - a_{ik-1}\frac{m_j}{m_{k-1}} = a_{ij} + a_{ik-1} m_j &amp; \text{ if } j \ne k-1 \\
\frac{a_{ik-1}}{m_{k-1}} = a_{ik-1} &amp; \text{ if } j = k-1
\end{cases}
\]</span></p>
<p>.. Update <span class="math inline">\(A\)</span> for all columns <span class="math inline">\(j = 1, \ldots, n\)</span> as follows: + <span class="math display">\[
\]</span></p></li>
<li><p>Update <span class="math inline">\(A\)</span> for all columns <span class="math inline">\(j = 1, \ldots, n\)</span> as follows <span class="math display">\[
\begin{aligned}
a_{ij} &amp;= b_{ij} \text{ for } i = 1, \ldots, k-2, \\
a_{k-1j} &amp;= \sum_{l=1}^{n} m_l b_{lj} = m \cdot \text{col}_j(B) \\
Expand All @@ -886,19 +890,24 @@ <h3 class="anchored" data-anchor-id="the-algorithm-1">The Algorithm</h3>
1 &amp; \text { for } j = k-1
\end{cases}
\end{aligned}
\]</span> + That last step puts row <span class="math inline">\(k\)</span> of <span class="math inline">\(A\)</span> into Frobenius form–the later rows of <span class="math inline">\(A\)</span> are already there.</p>
<p>.. If <span class="math inline">\(k &gt; 1\)</span> then <span class="math inline">\(k \leftarrow k-1\)</span> and we go back to step 1, otherwise we are done.</p>
<p>. If <span class="math inline">\(a_{kk-1} = 0\)</span> even after trying the search in step 2 then we cannot perform step 3. + Just like before, in this case the current <span class="math inline">\(A\)</span> matrix must have the following form: + <span class="math display">\[
\]</span> That last step puts row <span class="math inline">\(k\)</span> of <span class="math inline">\(A\)</span> into Frobenius form — later rows are already there.</p></li>
<li><p>If <span class="math inline">\(k &gt; 1\)</span> then <span class="math inline">\(k \gets k-1\)</span> and we go back to step 1, otherwise, we are done.</p></li>
</ul></li>
<li><p>If after step 2 we have <span class="math inline">\(a_{kk-1} = 0\)</span> then we cannot perform step 3.<br>
In this case, the current <span class="math inline">\(A\)</span> matrix must have the following form: <span class="math display">\[
A =
\begin{bmatrix}
A_1 &amp; A_2 \\
0 &amp; A_3
\end{bmatrix}
\]</span> hence the characteristic polynomial <span class="math inline">\(c_A(x)\)</span> we are after is the product of two other characteristic polynomials: + <span class="math display">\[
c_A(x) = c_{A_1}(x) c_{A_3}(x)
\]</span> + and as <span class="math inline">\(A_3\)</span> is already in Frobenius form we can easily read off the coefficients for <span class="math inline">\(c_{A_3}(x)\)</span>: + <span class="math display">\[
\]</span> hence the characteristic polynomial <span class="math inline">\(c_A(x)\)</span> is the product of two others:<br>
<span class="math display">\[
c_A(x) = c_{A_1}(x) c_{A_3}(x).
\]</span> As <span class="math inline">\(A_3\)</span> is already in Frobenius form we can easily read off the coefficients for <span class="math inline">\(c_{A_3}(x)\)</span>:<br>
<span class="math display">\[
c_{A_3}(x) = 1+ a_{kk} x + a_{kk+1} x^2 + \ldots + a_{kn} x^{n-k+1}.
\]</span> + The algorithm will store those coefficients and recurse using <span class="math inline">\(A_1\)</span> as the smaller <span class="math inline">\((k-1) \times (k-1)\)</span> input matrix. + It can then convolve the coefficients of <span class="math inline">\(c_{A_1}(x)\)</span> and <span class="math inline">\(c_{A_3}(x)\)</span> to return the coefficients for <span class="math inline">\(c_{A}(x)\)</span>.</p>
\]</span> Store those coefficients and recurse using <span class="math inline">\(A_1\)</span> as the <span class="math inline">\((k-1) \times (k-1)\)</span> input matrix. Convolve the coefficients of <span class="math inline">\(c_{A_1}(x)\)</span> and <span class="math inline">\(c_{A_3}(x)\)</span> to get the coefficients for <span class="math inline">\(c_{A}(x)\)</span>.</p></li>
</ol>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
Expand Down
2 changes: 1 addition & 1 deletion content/notes/gf2.html
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ <h2 class="anchored" data-anchor-id="some-things-are-simpler">Some things are si
<section id="gaussian-elimination-in-ff" class="level2">
<h2 class="anchored" data-anchor-id="gaussian-elimination-in-ff">Gaussian Elimination in <span class="math inline">\(\FF\)</span></h2>
<p>Suppose that <span class="math inline">\(A\)</span> is an <span class="math inline">\(n \times n\)</span> matrix over <span class="math inline">\(\FF\)</span> and <span class="math inline">\(b\)</span> is a compatibly sized bit-vector where we are interested in finding an <span class="math inline">\(x\)</span> satisfying <span class="math inline">\(A \cdot x = b\)</span>. Then the pseudocode for Gaussian elimination looks like:</p>
<div id="alg-ge" class="pseudocode-container quarto-float" data-comment-delimiter="//" data-line-number="true" data-indent-size="1.2em" data-line-number-punc=":" data-pseudocode-number="1" data-no-end="false" data-caption-prefix="Algorithm">
<div id="alg-ge" class="pseudocode-container quarto-float" data-pseudocode-number="1" data-caption-prefix="Algorithm" data-no-end="false" data-line-number="true" data-indent-size="1.2em" data-comment-delimiter="//" data-line-number-punc=":">
<div class="pseudocode">
\begin{algorithm} \caption{Gaussian Elimination in $F_2$} \begin{algorithmic} \Procedure{Solve}{$A, b, n$} \For {$j = 0$ \To $n - 1$} \State $s = j$ \While {$A(s,j) = 0$} \State $s = s + 1$ \EndWhile \If {$s &gt; n$} \Continue \EndIf \If {$ s \ne j$} \State swap rows $s$ and $j$ in the matrix $A$ \State swap elements $s$ and $j$ in the vector $b$ \EndIf \For {$i = j+1$ \To $n$} \If {$A(i,j) == 1$} \State replace row $i$ in $A$ with the sum of rows $i$ and $j$ \State replace element $i$ in $b$ with the sum of elements $i$ and $j$ \EndIf \EndFor \EndFor \EndProcedure \end{algorithmic} \end{algorithm}
</div>
Expand Down
6 changes: 3 additions & 3 deletions content/notes/reduction.html
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ <h2 class="anchored" data-anchor-id="a-multiply-square-technique-for-xn-mod-px">
</table>
</div>
<p>With those in place we can proceed as follows (this is just a sketch):</p>
<div id="multiply_and_square" class="pseudocode-container quarto-float" data-pseudocode-number="1" data-caption-prefix="Algorithm">
<div id="multiply_and_square" class="pseudocode-container quarto-float" data-caption-prefix="Algorithm" data-pseudocode-number="1">
<div class="pseudocode">
\begin{algorithm} \caption{Modular Reduction of $x^N$} \begin{algorithmic} \Require $\mathbf{p}$, a bit-vector of size $n$, where $P(x) = x^n + p(x)$ and $\mathbf{p} \sim p(x)$. Unchanged on output. \Require $\mathbf{r}$, a destination bit-vector of size $n$. On output $\mathbf{r} \sim r(x) = x^N \mid P(x)$. \Procedure{reduce}{$N$, $\mathbf{p}$} \State $\mathbf{r} \gets \mathbf{0}$ \State $r_1 = 1$ \While{$N &gt; 0$} \If{$N \text{ mod } 2 = 1$} \State \Call{MultiplyStep}{$\mathbf{r}$} \EndIf \State \Call{SquareStep}{$\mathbf{r}$} \State $N \gets N \gg 1$ \EndWhile \EndProcedure \end{algorithmic} \end{algorithm}
</div>
Expand All @@ -696,7 +696,7 @@ <h3 class="anchored" data-anchor-id="the-multiply-step">The Multiply Step</h3>
\]</span> then the following procedure performs the step <span class="math display">\[
q(x) \gets x q(x) \mod P(x),
\]</span> where <span class="math inline">\(q(x)\)</span> is represented by the bit-vector of its <span class="math inline">\(n\)</span> coefficients <span class="math inline">\(\bold{q} = [q_0, q_1, \ldots, q_{n-1}]\)</span>.</p>
<div id="MultiplyStep" class="pseudocode-container quarto-float" data-pseudocode-number="2" data-caption-prefix="Algorithm">
<div id="MultiplyStep" class="pseudocode-container quarto-float" data-caption-prefix="Algorithm" data-pseudocode-number="2">
<div class="pseudocode">
\begin{algorithm} \caption{The step: $q(x) \gets x q(x) \mid P(x)$.} \begin{algorithmic} \Require $\mathbf{p} \sim p(x)$ is a known bit-vector of size $n$, where $P(x) = x^n + p(x)$. \Require $\mathbf{q}$ is a bit-vector of size $n &gt; 0$. \Procedure{MultiplyStep}{$\mathbf{q}$} \State $tmp \gets q_{n-1}$ \State $\mathbf{q} \gets \mathbf{q} \gg 1$ \If {$tmp$} \State $\mathbf{q} \gets \mathbf{q} \wedge \mathbf{p}$ \EndIf \EndProcedure \end{algorithmic} \end{algorithm}
</div>
Expand Down Expand Up @@ -734,7 +734,7 @@ <h3 class="anchored" data-anchor-id="the-square-step">The Square Step</h3>
\bold{x}^0 = \bold{p}.
\]</span> With that starting point, we can easily fill in bit vectors <span class="math inline">\(\bold{x}^i\)</span> for <span class="math inline">\(i = 1, \ldots, n-1\)</span> by using <a href="#MultiplyStep" class="quarto-xref">Algorithm 2</a>.</p>
<p>The squaring step looks like the following:</p>
<div id="SquareStep" class="pseudocode-container quarto-float" data-pseudocode-number="3" data-caption-prefix="Algorithm">
<div id="SquareStep" class="pseudocode-container quarto-float" data-caption-prefix="Algorithm" data-pseudocode-number="3">
<div class="pseudocode">
\begin{algorithm} \caption{The step: $q(x) \gets q(x)^2 \mid P(x)$.} \begin{algorithmic} \Require $\mathbf{p} \sim p(x)$ is a known bit-vector of size $n$, where $P(x) = x^n + p(x)$. \Require $\mathbf{x}^i$ are known bit-vectors, where $\mathbf{x}^i \sim x^{n+i} \mid P(x)$. \Require $\mathbf{s}, \mathbf{l}$ and $\mathbf{h}$ are available workspace bit-vectors. \Require $\mathbf{q}$ is a bit-vector of size $n &gt; 0$. \Procedure{SquareStep}{$\mathbf{q}$} \State // \textit{Riffle $\mathbf{q}$ into $\mathbf{s}$.} \State \Call{riffle}{$\mathbf{q}$, $\mathbf{s}$} \State // \textit{Fill $\mathbf{l}$ with a copy of the first $n$ elements from $\mathbf{s}$ and $\mathbf{h}$ with the rest.} \State \Call{split}{$\mathbf{s}$, $n$, $\mathbf{l}$, $\mathbf{h}$} \State $\mathbf{q} \gets \mathbf{l}$ \For {$i \gets 0, n-1$} \If{$h_i$} \State $\mathbf{q} \gets \mathbf{q} \wedge \mathbf{x}^i$ \EndIf \EndFor \EndProcedure \end{algorithmic} \end{algorithm}
</div>
Expand Down
Loading

0 comments on commit a34263f

Please sign in to comment.