Jekyll2019-07-09T11:05:59-04:00https://blog.joey-dumont.ca/feed.xmlStudy of NatureA personal blog rooted in my interest for physics, mathematics, technology and literature. Might contain content inappropriate for the non-initiated.
Building a multilib MIPS toolchain: my journey through gcc’s build system2019-07-09T00:00:00-04:002019-07-09T00:00:00-04:00https://blog.joey-dumont.ca/building-a-multilib-mips-toolchain<p>This article assumes that you know to compile a cross-compiler from scratch. If
not, I recommend this <a href="http://www.ifp.illinois.edu/~nakazato/tips/xgcc.html#binutil">succinct
guide</a>, or this
<a href="https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/">longer guide</a>
if you want to have some context.</p>
<p>On x86_64 architectures, building gcc such that it can generate both 32- and 64-bit code is
easy: just use the <code class="highlighter-rouge">--enable-multilib</code> flag at configuration time, and
everything will follow smoothly (see Arch Linux’s PKGBUILD for
<a href="https://git.archlinux.org/svntogit/packages.git/tree/trunk/PKGBUILD?h=packages/gcc">gcc</a>,
the packaging is a bit more complicated, but the build itself is simple).</p>
<p>It is not as easy when targeting the MIPS architecture, specifically
<code class="highlighter-rouge">mips64-elf</code>. By default, the 32-bit ABIs are not part of the multilib setup.
gcc exposes the multilib setup that was used to compile a toolchain via the
<code class="highlighter-rouge">-print-multi-lib</code> option. On your own x86_64 system, you should see something
similar to this (assuming you have <code class="highlighter-rouge">gcc-multilib</code> on your system)</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>valandil ~ <span class="nv">$ </span>gcc -print-multi-lib
.;
32;@m32
</code></pre>
</div>
<p>where the second line shows the use of <code class="highlighter-rouge">-m32</code> in the build options for the gcc
toolchain itself, and the libraries are stored in the <code class="highlighter-rouge">32/</code> directory. This
toolchain is thus comprised of two sets of GCC libraries, one compiled with
default options, and one with <code class="highlighter-rouge">-m32</code>.</p>
<p>If you had installed a mips64-elf toolchain with <code class="highlighter-rouge">--enable-multilib</code>, by default
you would get the following output</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>valandil ~ <span class="nv">$ </span>mips64-elf-gcc -print-multi-lib
.;
soft-float;@msoft-float
el;@EL
soft-float/el;@msoft-float@EL
</code></pre>
</div>
<p>In order to enable other ABIs, specify other build options for the GCC libraries
in general, you need to know about <em><a href="https://gcc.gnu.org/onlinedocs//gcc-3.4.5/gccint/Target-Fragment.html">Target makefile
fragments</a></em>.</p>
<p>In short, target Makefile fragments are the <code class="highlighter-rouge">gcc/config/<target>/t*</code> files in
gcc’s source tree. When you specify a target at the <code class="highlighter-rouge">configure</code> step, it looks
for those in order to generate the Makefile that will actually build the gcc
libraries <sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup>. For a <code class="highlighter-rouge">mips64-elf</code> target, the file that is of interest to us is
the <code class="highlighter-rouge">gcc/config/mips/t-elf</code> file. By default, it sets three Makefile variables</p>
<div class="language-make highlighter-rouge"><pre class="highlight"><code><span class="nv">MULTILIB_OPTIONS</span> <span class="o">=</span> msoft-float EL/EB
<span class="nv">MULTILIB_DIRNAMES</span> <span class="o">=</span> soft-float el eb
<span class="nv">MULTILIB_MATCHES</span> <span class="o">=</span> <span class="nv">EL</span><span class="o">=</span>mel <span class="nv">EB</span><span class="o">=</span>meb msingle-float<span class="o">=</span>m4650
</code></pre>
</div>
<p>which instructs the gcc build system to generate libraries for combinations of
these three build flags. Flags that are separated by a space are combined, while
incompatible flag are separated with a slash. It is this fragment that generated
the <code class="highlighter-rouge">mips64-elf-gcc -print-multi-lib</code> output that we saw above.</p>
<p>So, if you want to generate libraries for other ABIs, you simply edit (or create
a new one!) that file to what you need. In my case, I wanted to have libraries
compiled with <code class="highlighter-rouge">-mabi=32</code>, at it is the ABI used by most N64 games. So, I edited
my <code class="highlighter-rouge">t-elf</code> fragment to be</p>
<div class="language-make highlighter-rouge"><pre class="highlight"><code><span class="nv">MULTILIB_OPTIONS</span> <span class="o">=</span> <span class="nv">mabi</span><span class="o">=</span>32 msoft-float EL/EB
<span class="nv">MULTILIB_DIRNAMES</span> <span class="o">=</span> 32 soft-float el eb
<span class="nv">MULTILIB_MATCHES</span> <span class="o">=</span> <span class="nv">EL</span><span class="o">=</span>mel <span class="nv">EB</span><span class="o">=</span>meb msingle-float<span class="o">=</span>m4650
</code></pre>
</div>
<p>If you were to compile this toolchain, you would get the following
<code class="highlighter-rouge">-print-multib-lib</code> output:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>.;
32;@mabi<span class="o">=</span>32
soft-float;@msoft-float
el;@EL
soft-float/el;@msoft-float@EL
32/soft-float;@mabi<span class="o">=</span>32@msoft-float
32/el;@mabi<span class="o">=</span>32@EL
32/soft-float/el;@mabi<span class="o">=</span>32@msoft-float@EL
</code></pre>
</div>
<p><code class="highlighter-rouge">MULTILIB_DIRNAMES</code> controls the name of the folder in which the libraries
reside. Note that this corresponds to the information before the semi-colon in
the <code class="highlighter-rouge">-print-multilib-output</code>, while the string after describes the build
options, preppended with <code class="highlighter-rouge">@</code>. and <code class="highlighter-rouge">MULTILIB_MATCHES</code> provides the synonyms of
some build options.</p>
<p>There are other options than those discussed here. Feel free to read the
<a href="https://gcc.gnu.org/onlinedocs//gcc-3.4.5/gccint/Fragments.html#Fragments">Makefile
Fragment</a>
of the gcc docs to have the whole story, or look at an example of custom target
in <a href="https://github.com/glankk">glank</a>’s <a href="https://github.com/glankk/n64/">n64
repo</a>, under config (as of July 9th, this is
only in the n64-ultra branch).</p>
<div class="footnotes">
<ol>
<li id="fn:1">
<p>At least, that is how I think it works. <a href="#fnref:1" class="reversefootnote">↩</a></p>
</li>
</ol>
</div>Joey Dumontme@joey-dumont.caThis article assumes that you know to compile a cross-compiler from scratch. If not, I recommend this succinct guide, or this longer guide if you want to have some context.Converting between different Zernike polynomial index systems2018-09-27T00:00:00-04:002018-09-27T00:00:00-04:00https://blog.joey-dumont.ca/zernike-polynomials-coefficients<p>The Zernike polynomials are a very popular basis to describe aberrations in the
wavefront of optical beams. They are used in ophthalmology <a class="citation" href="#Thibos2000"> [1]</a>, microscopy, and laser metrology, among others <a class="citation" href="#Wyant1992"> [2]</a>. Because they are orthogonal on the unit disk, they are most
suitable to describe deviations from a flat phase front in a single transverse
plane of the beam.</p>
<p>They are given by</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{align}
Z_{n}^{m}(\rho,\phi) &= R_{n}^{m}(\rho)\cos(m\phi) & (m\geq0) \\
Z_{n}^{m}(\rho,\phi) &= R_{n}^{|m|}(\rho)\sin(|m|\phi) & (m<0)
\end{align} %]]></script>
<p>where we can verify that they are indeed orthogonal on the unit disk:</p>
<script type="math/tex; mode=display">\int_0^1\int_0^{2\pi} Z_{n}^{m}Z_{n'}^{m'}\rho d\rho d\phi
= \frac{(1+\delta_{m,0})\pi}{2n+2}\delta_{n,n'}\delta_{m,m'}.</script>
<p>For a given value of <script type="math/tex">n\in\{\{0\}\cup\mathbb{N}\}=\mathbb{N}_0</script>, the possible
<script type="math/tex">m</script> values are in the range <script type="math/tex">m\in\{-n,n\}</script> and increase in increments of 2.
To simplify the enumeration of Zernike polynomials, various linear index schemes
have been devised. In short, each possible pair of <script type="math/tex">(n,m)</script> is assigned to a
monotonically increasing index that we will denote <script type="math/tex">j</script>. In this post, we’ll go
over some index schemes and write Python scripts that will allow us to map form
the linear index <script type="math/tex">j</script> to the quantum pair <script type="math/tex">(n,m)</script>. First, however, it will be
useful to investigate the structure of the pairs.</p>
<h3 id="the-triangular-structure-of-the-quantum-pairs">The Triangular Structure of the Quantum Pairs</h3>
<p>By simply enumerating the quantum pairs and arranging them on a grid where
rows indicate the value of <script type="math/tex">n</script> and columns the value of <script type="math/tex">m</script>, their triangular
structure becomes readily apparent.</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{matrix}
& & & (0,0) & & & \\
& & (1,-1) & & (1,1) & & \\
& (2,-2) & & (2,0) & & (2,2) & \\
(3,-3) & & (3,-1) & & (3,1) & & (3,3)
\end{matrix} %]]></script>
<p>Since each row contains one element more than the previous row, the number of
elements contained in the first <script type="math/tex">k</script> rows is given by the <script type="math/tex">k</script>th triangular
number <script type="math/tex">T_k</script>, defined by</p>
<script type="math/tex; mode=display">T_k = \sum_{i=1}^{n} i = \frac{k(k+1)}{2}.</script>
<p>For index systems that are monotonic in <script type="math/tex">n</script>, i.e. most of them, we can
directly relate the quantum number <script type="math/tex">n</script> to the index of the smallest triangular
number larger than <script type="math/tex">j</script>. Fortunately, the index can easily be determined via
the formula <a class="citation" href="#DAurizio2015"> [3]</a></p>
<script type="math/tex; mode=display">k = \left\lceil \frac{1+\sqrt{1+8n}}{2} \right\rceil - 1.</script>
<p>The remainder <script type="math/tex">r=j-T_k+n</script> can then be used to determine what column corresponds
to that particular <script type="math/tex">j</script> value. The various linear schemes use different rules
to assign a column to the remainder.</p>
<h3 id="noll-indices">Noll Indices</h3>
<p>The rules to assign the Noll index is to have it monotonic in <script type="math/tex">n</script> and then
assign in order of increasing <script type="math/tex">|m|</script>, where odd indices correspond to negative
values of <script type="math/tex">m</script> and even indices to positive values of <script type="math/tex">m</script>. The correspondence
between the Noll indices and the quantum pairs is the subject of OEIS sequence
A176988 <a class="citation" href="#A176988"> [4]</a>.</p>
<p>Since the Noll indices start at 1, the first quantum number can be written
as one less than the triangular number index, <script type="math/tex">n=k-1</script>.</p>
<p>The <script type="math/tex">m</script> value can be computed from the remainder <script type="math/tex">r=j-T_k+n</script>. The latter can
serve as an index into the list <code class="highlighter-rouge">m = [k for k in range(-n,n+2,2)]</code>, as it
guaranteed to lie in the range <script type="math/tex">[0,n-1]</script>. Because of the rules governing the
assignment of signs, using the remainder directly as an index into this list is
rather tedious. A simpler way is to create a list that generates all the
possible values of <script type="math/tex">|m|</script> and sort them in ascending order. For <script type="math/tex">n=3</script>, that
list would be <code class="highlighter-rouge">[1,1,3,3]</code>. <script type="math/tex">r</script> can be used as an index in this list to
determine the value of <script type="math/tex">|m|</script>. The sign is then decided by the parity of <script type="math/tex">j</script>
directly, as stated by the Noll rules.</p>
<p>Here’s the Python code that implements this (a C++ implementation is available
as part of my
<a href="https://github.com/joeydumont/zernike/blob/9eff81ebec7f0ef579ff01bfaabe23ff7ce8291c/src/zernike_indices.cpp#L41">Zernike</a>
library)</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="kn">as</span> <span class="nn">np</span>
<span class="k">def</span> <span class="nf">NollToQuantum</span><span class="p">(</span><span class="n">j</span><span class="p">):</span>
<span class="n">triangular_numbers_idx</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">ceil</span><span class="p">((</span><span class="mi">1</span><span class="o">+</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="mi">8</span><span class="o">*</span><span class="n">j</span><span class="p">))</span><span class="o">/</span><span class="mi">2</span><span class="p">),</span><span class="n">dtype</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span>
<span class="n">triangular_numbers</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">indices</span><span class="o">*</span><span class="p">(</span><span class="n">indices</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">indices</span> <span class="o">-</span> <span class="mi">1</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">triangular_numbers</span>
<span class="n">rpn</span> <span class="o">=</span> <span class="n">r</span><span class="o">+</span><span class="n">n</span>
<span class="c"># -- Have to work value-per-value here.</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="o">.</span><span class="n">size</span><span class="p">):</span>
<span class="n">m_vec</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="n">j</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="n">n</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">n</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">)])</span>
<span class="n">m_vec</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">m_vec</span><span class="p">))</span>
<span class="n">m</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="n">j</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">%</span><span class="mi">2</span><span class="p">)</span><span class="o">*</span><span class="n">m_vec</span><span class="p">[</span><span class="n">rpn</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span>
<span class="k">return</span> <span class="n">n</span><span class="p">,</span> <span class="n">m</span>
</code></pre>
</div>
<p><script type="math/tex">m</script> could be computed directly via the one-liner</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="n">m</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="n">j</span> <span class="o">*</span> <span class="p">((</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">((</span><span class="n">r</span> <span class="o">+</span> <span class="p">((</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">%</span><span class="mi">2</span><span class="p">))</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">int</span><span class="p">))</span>
</code></pre>
</div>
<p>but in practice I found the code above to be faster, even though
it generated a larger bytecode than the one-liner version.</p>
<p>Let’s work through an example value.
For instance, suppose that we have <script type="math/tex">j=8</script>, then the formula above <script type="math/tex">k=4</script> and thus <script type="math/tex">n=3</script>.
The remainder is <script type="math/tex">r=8-10+3=1</script>. From our list above, we have that <script type="math/tex">|m|=1</script>.
Since <script type="math/tex">j</script> is even, <script type="math/tex">m</script> is positive, and we have <script type="math/tex">m=1</script>.
And indeed, <script type="math/tex">(j=8)\mapsto(3,1)</script>.</p>
<h3 id="phasics-indices">Phasics Indices</h3>
<p>The Phasics index system is monotonic in <script type="math/tex">n</script>, as Noll’s is, and also monotonic
in <script type="math/tex">|m|</script>. However, this system elects to always assign positive values of
<script type="math/tex">m</script> to lower linear indices, regardless of parity, as stated in the SID4 6.4
User Handbook, Chapter 6.</p>
<p>From these characteristics, we see that Noll and Phasics only differ on rows
where <script type="math/tex">T_n</script> is even, as We can thus use the same basic function above, but
add the single-line</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="n">m</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="n">triangular_numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">%</span><span class="mi">2</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
</code></pre>
</div>
<p>at the end of the loop.</p>
<h3 id="sources">Sources</h3>
<ol class="bibliography"><li><span id="Thibos2000">L. Thibos, R. A. Applegate, J. T. Schwiegerling, and R. Webb, "Standards for reporting the optical aberrations of eyes," in <i>Vision Science and Its Applications</i> (Optical Society of America, 2000), p. SuC1.</span></li>
<li><span id="Wyant1992">J. C. Wyant and K. Creath, "Basic Wavefront Aberration Theory for Optical Metrology," in <i>Applied Optics and Optical Engineering, Volume XI</i>, R. R. Shannon and J. C. Wyant, eds. (1992), Vol. XI.</span></li>
<li><span id="DAurizio2015">J. D’Aurizio, "Largest Triangular Number less than a Given Natural Number," <a href="https://math.stackexchange.com/q/1417583">https://math.stackexchange.com/q/1417583</a>", accessed Sep. 26th, 2018.</span></li>
<li><span id="A176988">R. J. Mathar, "A176988: Triangle read by rows which contains Noll’s indices of Zernike polynomials in row n sorted along increasing index of the azimuthal quantum number," <a href="https://oeis.org/A176988">https://oeis.org/A176988</a>, accessed Sep. 26th, 2018.</span></li></ol>
<h3 id="appendix-table-of-index-values-generated-by-the-algorithm">Appendix: Table of index values generated by the algorithm</h3>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
text-align: left;
padding: 8px;
}
tr:nth-child(even) {background-color: #f2f2f2;}
</style>
<table>
<thead>
<tr>
<th><script type="math/tex">j</script> </th>
<th>Noll</th>
<th>Phasics</th>
</tr>
</thead>
<tbody>
<tr>
<td><script type="math/tex">1</script></td>
<td><script type="math/tex">(0,0)</script></td>
<td><script type="math/tex">(0,0)</script></td>
</tr>
<tr>
<td><script type="math/tex">2</script></td>
<td><script type="math/tex">(1,1)</script></td>
<td><script type="math/tex">(1,1)</script></td>
</tr>
<tr>
<td><script type="math/tex">3</script></td>
<td><script type="math/tex">(1,-1)</script></td>
<td><script type="math/tex">(1,-1)</script></td>
</tr>
<tr>
<td><script type="math/tex">4</script></td>
<td><script type="math/tex">(2,0)</script></td>
<td><script type="math/tex">(2,0)</script></td>
</tr>
<tr>
<td><script type="math/tex">5</script></td>
<td><script type="math/tex">(2,-2)</script></td>
<td><script type="math/tex">(2,2)</script></td>
</tr>
<tr>
<td><script type="math/tex">6</script></td>
<td><script type="math/tex">(2,2)</script></td>
<td><script type="math/tex">(2,-2)</script></td>
</tr>
<tr>
<td><script type="math/tex">7</script></td>
<td><script type="math/tex">(3,-1)</script></td>
<td><script type="math/tex">(3,1)</script></td>
</tr>
<tr>
<td><script type="math/tex">8</script></td>
<td><script type="math/tex">(3,1)</script></td>
<td><script type="math/tex">(3,-1)</script></td>
</tr>
<tr>
<td><script type="math/tex">9</script></td>
<td><script type="math/tex">(3,-3)</script></td>
<td><script type="math/tex">(3,3)</script></td>
</tr>
<tr>
<td><script type="math/tex">10</script></td>
<td><script type="math/tex">(3,3)</script></td>
<td><script type="math/tex">(3,-3)</script></td>
</tr>
<tr>
<td><script type="math/tex">11</script></td>
<td><script type="math/tex">(4,0)</script></td>
<td><script type="math/tex">(4,0)</script></td>
</tr>
<tr>
<td><script type="math/tex">12</script></td>
<td><script type="math/tex">(4,2)</script></td>
<td><script type="math/tex">(4,2)</script></td>
</tr>
<tr>
<td><script type="math/tex">13</script></td>
<td><script type="math/tex">(4,-2)</script></td>
<td><script type="math/tex">(4,-2)</script></td>
</tr>
<tr>
<td><script type="math/tex">14</script></td>
<td><script type="math/tex">(4,4)</script></td>
<td><script type="math/tex">(4,4)</script></td>
</tr>
<tr>
<td><script type="math/tex">15</script></td>
<td><script type="math/tex">(4,-4)</script></td>
<td><script type="math/tex">(4,-4)</script></td>
</tr>
<tr>
<td><script type="math/tex">16</script></td>
<td><script type="math/tex">(5,1)</script></td>
<td><script type="math/tex">(5,1)</script></td>
</tr>
<tr>
<td><script type="math/tex">17</script></td>
<td><script type="math/tex">(5,-1)</script></td>
<td><script type="math/tex">(5,-1)</script></td>
</tr>
<tr>
<td><script type="math/tex">18</script></td>
<td><script type="math/tex">(5,3)</script></td>
<td><script type="math/tex">(5,3)</script></td>
</tr>
<tr>
<td><script type="math/tex">19</script></td>
<td><script type="math/tex">(5,-3)</script></td>
<td><script type="math/tex">(5,-3)</script></td>
</tr>
<tr>
<td><script type="math/tex">20</script></td>
<td><script type="math/tex">(5,5)</script></td>
<td><script type="math/tex">(5,5)</script></td>
</tr>
<tr>
<td><script type="math/tex">21</script></td>
<td><script type="math/tex">(5,-5)</script></td>
<td><script type="math/tex">(5,-5)</script></td>
</tr>
<tr>
<td><script type="math/tex">22</script></td>
<td><script type="math/tex">(6,0)</script></td>
<td><script type="math/tex">(6,0)</script></td>
</tr>
<tr>
<td><script type="math/tex">23</script></td>
<td><script type="math/tex">(6,-2)</script></td>
<td><script type="math/tex">(6,2)</script></td>
</tr>
<tr>
<td><script type="math/tex">24</script></td>
<td><script type="math/tex">(6,2)</script></td>
<td><script type="math/tex">(6,-2)</script></td>
</tr>
<tr>
<td><script type="math/tex">25</script></td>
<td><script type="math/tex">(6,-4)</script></td>
<td><script type="math/tex">(6,4)</script></td>
</tr>
<tr>
<td><script type="math/tex">26</script></td>
<td><script type="math/tex">(6,4)</script></td>
<td><script type="math/tex">(6,-4)</script></td>
</tr>
<tr>
<td><script type="math/tex">27</script></td>
<td><script type="math/tex">(6,-6)</script></td>
<td><script type="math/tex">(6,6)</script></td>
</tr>
<tr>
<td><script type="math/tex">28</script></td>
<td><script type="math/tex">(6,6)</script></td>
<td><script type="math/tex">(6,-6)</script></td>
</tr>
<tr>
<td><script type="math/tex">29</script></td>
<td><script type="math/tex">(7,-1)</script></td>
<td><script type="math/tex">(7,1)</script></td>
</tr>
<tr>
<td><script type="math/tex">30</script></td>
<td><script type="math/tex">(7,1)</script></td>
<td><script type="math/tex">(7,-1)</script></td>
</tr>
<tr>
<td><script type="math/tex">31</script></td>
<td><script type="math/tex">(7,-3)</script></td>
<td><script type="math/tex">(7,3)</script></td>
</tr>
<tr>
<td><script type="math/tex">32</script></td>
<td><script type="math/tex">(7,3)</script></td>
<td><script type="math/tex">(7,-3)</script></td>
</tr>
<tr>
<td><script type="math/tex">33</script></td>
<td><script type="math/tex">(7,-5)</script></td>
<td><script type="math/tex">(7,5)</script></td>
</tr>
<tr>
<td><script type="math/tex">34</script></td>
<td><script type="math/tex">(7,5)</script></td>
<td><script type="math/tex">(7,-5)</script></td>
</tr>
<tr>
<td><script type="math/tex">35</script></td>
<td><script type="math/tex">(7,-7)</script></td>
<td><script type="math/tex">(7,7)</script></td>
</tr>
<tr>
<td><script type="math/tex">36</script></td>
<td><script type="math/tex">(7,7)</script></td>
<td><script type="math/tex">(7,-7)</script></td>
</tr>
<tr>
<td><script type="math/tex">37</script></td>
<td><script type="math/tex">(8,0)</script></td>
<td><script type="math/tex">(8,0)</script></td>
</tr>
<tr>
<td><script type="math/tex">38</script></td>
<td><script type="math/tex">(8,2)</script></td>
<td><script type="math/tex">(8,2)</script></td>
</tr>
<tr>
<td><script type="math/tex">39</script></td>
<td><script type="math/tex">(8,-2)</script></td>
<td><script type="math/tex">(8,-2)</script></td>
</tr>
<tr>
<td><script type="math/tex">40</script></td>
<td><script type="math/tex">(8,4)</script></td>
<td><script type="math/tex">(8,4)</script></td>
</tr>
<tr>
<td><script type="math/tex">41</script></td>
<td><script type="math/tex">(8,-4)</script></td>
<td><script type="math/tex">(8,-4)</script></td>
</tr>
<tr>
<td><script type="math/tex">42</script></td>
<td><script type="math/tex">(8,6)</script></td>
<td><script type="math/tex">(8,6)</script></td>
</tr>
<tr>
<td><script type="math/tex">43</script></td>
<td><script type="math/tex">(8,-6)</script></td>
<td><script type="math/tex">(8,-6)</script></td>
</tr>
<tr>
<td><script type="math/tex">44</script></td>
<td><script type="math/tex">(8,8)</script></td>
<td><script type="math/tex">(8,8)</script></td>
</tr>
<tr>
<td><script type="math/tex">45</script></td>
<td><script type="math/tex">(8,-8)</script></td>
<td><script type="math/tex">(8,-8)</script></td>
</tr>
<tr>
<td><script type="math/tex">46</script></td>
<td><script type="math/tex">(9,1)</script></td>
<td><script type="math/tex">(9,1)</script></td>
</tr>
<tr>
<td><script type="math/tex">47</script></td>
<td><script type="math/tex">(9,-1)</script></td>
<td><script type="math/tex">(9,-1)</script></td>
</tr>
<tr>
<td><script type="math/tex">48</script></td>
<td><script type="math/tex">(9,3)</script></td>
<td><script type="math/tex">(9,3)</script></td>
</tr>
<tr>
<td><script type="math/tex">49</script></td>
<td><script type="math/tex">(9,-3)</script></td>
<td><script type="math/tex">(9,-3)</script></td>
</tr>
<tr>
<td><script type="math/tex">50</script></td>
<td><script type="math/tex">(9,5)</script></td>
<td><script type="math/tex">(9,5)</script></td>
</tr>
</tbody>
</table>Joey Dumontme@joey-dumont.caThe Zernike polynomials are a very popular basis to describe aberrations in the wavefront of optical beams. They are used in ophthalmology [1], microscopy, and laser metrology, among others [2]. Because they are orthogonal on the unit disk, they are most suitable to describe deviations from a flat phase front in a single transverse plane of the beam.Loading complex numbers in the C++ format from text files into NumPy2018-07-24T00:00:00-04:002018-07-24T00:00:00-04:00https://blog.joey-dumont.ca/read-c-format-complex-numbers-with-numpy<p>In my workflow, I typically use C++ for production code and Python for data
post-processing and data analysis. A major annoyance is that NumPy’s
<code class="highlighter-rouge">genfromtxt</code> does not recognize the C++ complex number format.</p>
<p>Of course, one could write their own I/O for their C++ production codes, but
most libraries have built-in I/O functions and it’s just a pain. It’s much
easier to get Python to read the C++ format!</p>
<h3 id="the-issue">The Issue</h3>
<p>C++ represents a given complex number <script type="math/tex">z=a+ib</script> as <code class="highlighter-rouge">(a,b)</code>. When using
<code class="highlighter-rouge">genfromtxt</code> to read a file containing an array of complex numbers, the obvious</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="kn">as</span> <span class="nn">np</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">genfromtxt</span><span class="p">(</span><span class="s">"file"</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">complex</span><span class="p">)</span>
</code></pre>
</div>
<p>yields <code class="highlighter-rouge">NaN</code>s for the real part and <code class="highlighter-rouge">0</code>s for the imaginary part. To get Python
to understand the format, an easy solution is to first parse the elements of the
array as strings, then use a lambda function to effectively cast the strings
as complex numbers. Here’s the code.</p>
<h3 id="the-code">The Code</h3>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="k">def</span> <span class="nf">LoadComplexData</span><span class="p">(</span><span class="nb">file</span><span class="p">,</span><span class="o">**</span><span class="n">genfromtext_args</span><span class="p">):</span>
<span class="s">"""
Load complex data in the C++ format in numpy.
"""</span>
<span class="n">array_as_strings</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">genfromtext</span><span class="p">(</span><span class="nb">file</span><span class="p">,</span><span class="n">dtype</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span><span class="o">**</span><span class="n">genfromtext_args</span><span class="p">)</span>
<span class="n">complex_parser</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">vectorize</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">complex</span><span class="p">(</span><span class="o">*</span><span class="nb">eval</span><span class="p">(</span><span class="n">x</span><span class="p">)))</span>
<span class="k">return</span> <span class="n">complex_parser</span><span class="p">(</span><span class="n">array_as_strings</span><span class="p">)</span>
</code></pre>
</div>
<p>First, we load the array of complex numbers as an array of strings in Python.
Then, we use <code class="highlighter-rouge">np.vectorize</code> to define a callable that takes each of the array
and applies the <code class="highlighter-rouge">complex(*eval(x))</code> to it. <code class="highlighter-rouge">eval()</code> takes the string and evaluates
it to a tuple of floats. The <code class="highlighter-rouge">*</code> operator unpacks the tuple such that we are calling
<code class="highlighter-rouge">complex(a,b)</code> properly. This returns a complex number in Python format.</p>
<p>A solution based on a <code class="highlighter-rouge">genfromtxt</code> converter could be more elegant, but I wasn’t
able to find a way to apply a converter to every column of the input file
instead of a specific column.</p>
<p>You can try it for yourself with these
<a href="https://blog.joey-dumont.ca/assets/posts/read-c-format-complex-numbers-with-numpy/complex_data_example.tar.gz">files</a>. This was tested with Numpy v1.14.5.</p>Joey Dumontme@joey-dumont.caIn my workflow, I typically use C++ for production code and Python for data post-processing and data analysis. A major annoyance is that NumPy’s genfromtxt does not recognize the C++ complex number format.vnc through SSH: how to control your desktop remotely2018-01-17T00:00:00-05:002018-01-17T00:00:00-05:00https://blog.joey-dumont.ca/vnc-through-ssh-how-to-control-your-desktop-remotely<p>I won’t go into too much detail in this post, as there are <a href="http://www.cl.cam.ac.uk/research/dtg/attarchive/vnc/sshvnc.html">multiple</a> <a href="https://www.cyberciti.biz/tips/tunneling-vnc-connections-over-ssh-howto.html">guides</a>
that go above and beyond in explaining the behind-the-scenes of tunnelling
VNC connections through SSH. Note that this solution uses TigerVNC’s <code class="highlighter-rouge">x0vncserver</code>
to control the remote X server. Simply use <code class="highlighter-rouge">vncserver</code> if you want to control
a different X server.</p>
<p>The setup is quite simple, but requires two terminal windows. In the first terminal,
SSH into your remote machine with</p>
<pre class="highlight"><code><b>user@local-machine <span class="nv">$ </span></b>ssh -Y <remote.machine.com> -L 5900:localhost:5900
</code></pre>
<p>and then,</p>
<pre class="highlight"><code><b>remoteuser@remote-machine <span class="nv">$ </span></b> x0vncserver -display :0 -passwordfile ~/.vnc/passwd
</code></pre>
<p>Now, in the second terminal on your local machine, you can simply type</p>
<pre class="highlight"><code><b>user@local-machine <span class="nv">$</span></b> vncviewer localhost:5900
</code></pre>
<p></p>
<p>The <code class="highlighter-rouge">-L</code> flag in the SSH connection sets up port forwarding from the local machine
to the remote machine. In short, all unbound traffic that goes through the specified
port on the local machine is forward to the other port on the remote machine. Here we
choose port 5900 on both machines as it is the default port for <code class="highlighter-rouge">x0vncserver</code>,
but both can be changed freely.</p>
<p>Make sure to generate a password file for VNC by using <code class="highlighter-rouge">vncpasswd</code> and pass
it to <code class="highlighter-rouge">x0vncserver</code> on the <code class="highlighter-rouge">passwordfile</code> flag. Here we choose the default.</p>
<p>The same method with generic ports would read</p>
<pre class="highlight"><code><b>user@local-machine <span class="nv">$ </span></b>ssh -Y <remote.machine.com> -L <xxxx>:localhost:<yyyy>
<b>remoteuser@remote-machine <span class="nv">$ </span></b> x0vncserver -rfbport <yyyy> -display :0 \
-passwordfile ~/.vnc/passwd
</code></pre>
<div style="text-indent: 0">and</div>
<pre class="highlight"><code><b>user@local-machine <span class="nv">$</span></b> vncviewer localhost:<xxxx>
</code></pre>
<p>Until next time, cheers!</p>Joey Dumontme@joey-dumont.caI won’t go into too much detail in this post, as there are multiple guides that go above and beyond in explaining the behind-the-scenes of tunnelling VNC connections through SSH. Note that this solution uses TigerVNC’s x0vncserver to control the remote X server. Simply use vncserver if you want to control a different X server.Have yaourt save compiled packages to /var/cache/pacman/pkg2015-04-14T16:46:00-04:002015-04-14T16:46:00-04:00https://blog.joey-dumont.ca/have-yaourt-save-compiled-packages-to<div dir="ltr" style="text-align: left;" trbidi="on"> The title of this post might not mean much to most of you, but for those few lucky enough to use Arch Linux on a daily basis, this could be of use to you. By default, <i>yaourt</i> does not keep the package files it produces, it deletes them after installation. Since the AUR deals mostly with unsupported packages, making it imperative that you be able to roll back to older packages, this is not useful default behaviour. <br /><div dir="ltr" style="text-align: justify;" trbidi="on"> To have yaourt export your compiled packages to the standard location, /var/cache/pacman/pkg/, edit /etc/yaourtrc and change the line <br /><blockquote>#EXPORT=0</blockquote>to <br /><blockquote>EXPORT=2</blockquote>That is all. Have a nice day! </div></div>Joey Dumontme@joey-dumont.ca The title of this post might not mean much to most of you, but for those few lucky enough to use Arch Linux on a daily basis, this could be of use to you. By default, yaourt does not keep the package files it produces, it deletes them after installation. Since the AUR deals mostly with unsupported packages, making it imperative that you be able to roll back to older packages, this is not useful default behaviour. To have yaourt export your compiled packages to the standard location, /var/cache/pacman/pkg/, edit /etc/yaourtrc and change the line #EXPORT=0to EXPORT=2That is all. Have a nice day!Google Calendar Material Design2014-11-11T15:55:00-05:002014-11-11T15:55:00-05:00https://blog.joey-dumont.ca/google-calendar-material-design<div dir="ltr" style="text-align: justify;" trbidi="on"> My Nexus 4 prompted me last night for permission to update Gmail and <a href="https://play.google.com/store/apps/details?id=com.google.android.calendar&hl=en">Google Calendar</a>. I must say, while Gmail looks slightly better than it did, GCal has received a much needed revamp, especially the widget. I do not have a screenshot of the previous version, but the colour scheme was terrible and the layout was such that it was hard to determine the division between days. It was also very difficult to quickly glance at a calendar to get some information.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-0-HLzdJuoyE/VGJ3BDRi4iI/AAAAAAAAEAE/akFfFqq0RcM/s1600/Screenshot_2014-11-11-15-36-33.png" imageanchor="1" style="margin-left: auto; margin-right: auto; text-align: center;"><img border="0" height="320" src="https://2.bp.blogspot.com/-0-HLzdJuoyE/VGJ3BDRi4iI/AAAAAAAAEAE/akFfFqq0RcM/s320/Screenshot_2014-11-11-15-36-33.png" width="192" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">A screenshot of the new GCal widget<br />on my Nexus 4.</td></tr></tbody></table> The new version, released yesterday, has received the "Material Design" treatment; the colours are a little more tame, and the division between events and dates is much clearer. Worth the (free) update.<br /><br />I guess I'm saying I like the new designs of Google.</div>Joey Dumontme@joey-dumont.ca My Nexus 4 prompted me last night for permission to update Gmail and Google Calendar. I must say, while Gmail looks slightly better than it did, GCal has received a much needed revamp, especially the widget. I do not have a screenshot of the previous version, but the colour scheme was terrible and the layout was such that it was hard to determine the division between days. It was also very difficult to quickly glance at a calendar to get some information.A screenshot of the new GCal widgeton my Nexus 4. The new version, released yesterday, has received the "Material Design" treatment; the colours are a little more tame, and the division between events and dates is much clearer. Worth the (free) update.I guess I'm saying I like the new designs of Google.Dual basis and its applications2013-04-21T13:55:00-04:002013-04-21T13:55:00-04:00https://blog.joey-dumont.ca/dual-basis-and-its-applications<div dir="ltr" style="text-align: justify;" trbidi="on"> In the physical sciences, the scientist mostly tries to put the problem in a form that is easily solvable. One such form is the eigenvector expansion where one solves a simpler problem and assumes that the more difficult problem can be decomposed in a sum of the simpler solutions. </div> <div dir="ltr", style="text-align: justify;" trbidy="on"> This kind of problem generally involves solving the eigenvalue problem of a particular matrix. Assuming that you know how to do that, this is all fine and well. However, it is also common to use orthogonality relations to simplify the solution. For a general matrix $A$, the resulting eigenvectors need not be orthogonal. That's a problem. Let's look for a solution. </div> <div dir="ltr", style="text-align: justify;" trbidy="on"> Adopting the braket notation and denoting an eigenvector by $|e_i\rangle$, we seek new vectors such that $$ \langle f^i|e_j\rangle = \delta^i_j.$$ To see how we can compute those vectors, consider the original eigenvalue problem $$ \label{eq:eigenvalue}A|e_i\rangle = \lambda_i|e_i\rangle .$$ We will use the fact that both sets of eigenvectors are complete so that there exists a closure relation $$ \sum_i |e_i\rangle\langle f^i| = 1.$$ Now, pre-multipling \eqref{eq:eigenvalue} by $\langle f^j|$ and post-multiplying by $\langle f^i|$ and summing over the index $i$, we get $$ \sum_i \langle f^j|A|e_i\rangle\langle f^i| = \sum_i \lambda_i \langle f^j|e_i\rangle\langle f^i|.$$ Using our orthogonality relations on the right-hand side of this last equation and the closure relation on the left-hand side, we get $$ \langle f^j| A = \sum_i \lambda_i \langle f^i| \delta^j_i. $$ The Dirac delta makes the sum disappear as usual and we have $$ \langle f^j| A = \lambda_j \langle f^j|. $$ In other words, the $\langle f^j|$ are the row eigenvectors of $A$ and have the same eigenvalues as the set $|e_i\rangle$! </div> <div dir="ltr", style="text-align: justify;" trbidy="on"> So we find that these new "contravariant" vectors are actually the <i>left eigenvectors</i> of the matrix $A$. Moreover, the decomposition of any vector in the original set of covariant vectors is given by the dot product with the vectors in the dual basis. Say we have a vector $|v\rangle$, its decomposition is given by $$ |v\rangle = \sum_i \langle f^i|v\rangle|e_i\rangle .$$ </div> <div dir="ltr", style="text-align: justify;" trbidy="on"> This eigendecomposition is incredibly useful in solving differential equations, smoothing numerically unstable solutions... </div>Joey Dumontme@joey-dumont.ca In the physical sciences, the scientist mostly tries to put the problem in a form that is easily solvable. One such form is the eigenvector expansion where one solves a simpler problem and assumes that the more difficult problem can be decomposed in a sum of the simpler solutions. This kind of problem generally involves solving the eigenvalue problem of a particular matrix. Assuming that you know how to do that, this is all fine and well. However, it is also common to use orthogonality relations to simplify the solution. For a general matrix $A$, the resulting eigenvectors need not be orthogonal. That's a problem. Let's look for a solution. Adopting the braket notation and denoting an eigenvector by $|e_i\rangle$, we seek new vectors such that $$ \langle f^i|e_j\rangle = \delta^i_j.$$ To see how we can compute those vectors, consider the original eigenvalue problem $$ \label{eq:eigenvalue}A|e_i\rangle = \lambda_i|e_i\rangle .$$ We will use the fact that both sets of eigenvectors are complete so that there exists a closure relation $$ \sum_i |e_i\rangle\langle f^i| = 1.$$ Now, pre-multipling \eqref{eq:eigenvalue} by $\langle f^j|$ and post-multiplying by $\langle f^i|$ and summing over the index $i$, we get $$ \sum_i \langle f^j|A|e_i\rangle\langle f^i| = \sum_i \lambda_i \langle f^j|e_i\rangle\langle f^i|.$$ Using our orthogonality relations on the right-hand side of this last equation and the closure relation on the left-hand side, we get $$ \langle f^j| A = \sum_i \lambda_i \langle f^i| \delta^j_i. $$ The Dirac delta makes the sum disappear as usual and we have $$ \langle f^j| A = \lambda_j \langle f^j|. $$ In other words, the $\langle f^j|$ are the row eigenvectors of $A$ and have the same eigenvalues as the set $|e_i\rangle$! So we find that these new "contravariant" vectors are actually the left eigenvectors of the matrix $A$. Moreover, the decomposition of any vector in the original set of covariant vectors is given by the dot product with the vectors in the dual basis. Say we have a vector $|v\rangle$, its decomposition is given by $$ |v\rangle = \sum_i \langle f^i|v\rangle|e_i\rangle .$$ This eigendecomposition is incredibly useful in solving differential equations, smoothing numerically unstable solutions...Interfacing Armadillo and FFTW2013-03-10T23:31:00-04:002013-03-10T23:31:00-04:00https://blog.joey-dumont.ca/interfacing-armadillo-and-fftw<div dir="ltr" style="text-align: justify;" trbidi="on"> FFTW, or the <i><a href="http://fftw.org/">Fastest Fourier Transform in the West</a></i>, is an awesome C library used to, well, perform FFTs. <a href="http://arma.sourceforce.net/">Armadillo</a>, on the other hand, is an awesome C++ library that implements linear algebra operations. Both are renowned for their amazing speed and, especially the latter, ease of use. </div><div dir="ltr" style="text-align: justify;" trbidi="on"> Now suppose you want to use Armadillo in concert with FFTW. By default, FFTW assumes that you are using <span style="font-family: Courier New, Courier, monospace;">fftw_complex*</span> arrays which memory are allocated using <span style="font-family: Courier New, Courier, monospace;">fftw_malloc</span>. Now, assuming that you want to transform elements of an Armadillo vector or matrix, copying the data from the matrix to a newly allocated array may not be desirable (or it might be, depending on the performance hit incurred by not using <span style="font-family: Courier New, Courier, monospace;">fftw_malloc</span>). Then, your C++ code should be something like <script src="https://gist.github.com/valandil/cc98f474360f027240f8.js"></script></div><div dir="ltr" style="text-align: justify;" trbidi="on"> I'm by no means an expert, but this snippet works beautifully in my own code. </div><div dir="ltr" style="text-align: justify;" trbidi="on"> Please feel free to point out any factual errors. </div><div dir="ltr" style="text-align: justify;" trbidi="on"><b>Update:</b> Note that the operations in the Gist do not commute, i.e. the order in which they are done is important. If you put data in the <span style="font-family: Courier New, Courier, monospace;">samples</span>matrix before creating the plan, your columns will be overwritten. Pay attention! </div>Joey Dumontme@joey-dumont.ca FFTW, or the Fastest Fourier Transform in the West, is an awesome C library used to, well, perform FFTs. Armadillo, on the other hand, is an awesome C++ library that implements linear algebra operations. Both are renowned for their amazing speed and, especially the latter, ease of use. Now suppose you want to use Armadillo in concert with FFTW. By default, FFTW assumes that you are using fftw_complex* arrays which memory are allocated using fftw_malloc. Now, assuming that you want to transform elements of an Armadillo vector or matrix, copying the data from the matrix to a newly allocated array may not be desirable (or it might be, depending on the performance hit incurred by not using fftw_malloc). Then, your C++ code should be something like I'm by no means an expert, but this snippet works beautifully in my own code. Please feel free to point out any factual errors. Update: Note that the operations in the Gist do not commute, i.e. the order in which they are done is important. If you put data in the samplesmatrix before creating the plan, your columns will be overwritten. Pay attention!Arrow in the Knee: the Genesis2013-01-24T01:06:00-05:002013-01-24T01:06:00-05:00https://blog.joey-dumont.ca/arrow-in-knee-genesis<div dir="ltr" style="text-align: left;" trbidi="on"> So my wife was re-reading the epic fantasy pentalogy <i>The Belgariad </i>by David Eddings [1]. It's a fantastic coming-of-age, prophecy-fulfilling, magic-filled story. Every character is fully developed and they are all thoroughly likable. <br /><br /><div dir="ltr" style="text-align: justify;" trbidi="on"> But now to the important part. In the <i>Queen of Sorcery</i> book [2,p.222], originally published in 1982, it is revealed that Count Reldegen, an Asturian, is limping. This sparks the following conversation: <br /><blockquote>"What happened to your leg?" Wolf asked him. <br />"An arrow in the knee." The count shrugged.</blockquote>Yes, that's right, an <i>arrow in the knee</i>! </div><br /><div dir="ltr" style="text-align: justify;" trbidi="on"> Now go read <i>The Belgariad</i> so you know why it matters that Reldegen is an Asturian. </div><br /><div id="#ft1">[1] Amateurish introductory line, I know.</div><div id="#ft2">[2] D. Eddings. <i>Queen of Sorcery</i> in <i>The Belgariad</i>. 2002. New York: Ballantine.</div></div>Joey Dumontme@joey-dumont.ca So my wife was re-reading the epic fantasy pentalogy The Belgariad by David Eddings [1]. It's a fantastic coming-of-age, prophecy-fulfilling, magic-filled story. Every character is fully developed and they are all thoroughly likable. But now to the important part. In the Queen of Sorcery book [2,p.222], originally published in 1982, it is revealed that Count Reldegen, an Asturian, is limping. This sparks the following conversation: "What happened to your leg?" Wolf asked him. "An arrow in the knee." The count shrugged.Yes, that's right, an arrow in the knee! Now go read The Belgariad so you know why it matters that Reldegen is an Asturian. [1] Amateurish introductory line, I know.[2] D. Eddings. Queen of Sorcery in The Belgariad. 2002. New York: Ballantine.(Literary) Ramblings about the Universe2012-09-08T00:19:00-04:002012-09-08T00:19:00-04:00https://blog.joey-dumont.ca/literary-ramblings-about-universe<div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;"> While sipping away at my alcoholic drink, I had, as men usually have, philosophical matters spring to my mind. Wrought body and soul in the shadow of the night, my first instinct was to share my thoughts with the world.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"> In <a href="http://www.amazon.ca/gp/product/0553208845/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=15121&creative=330641&creativeASIN=0553208845&linkCode=as2&tag=blogjoeydumon-20" target="_blank">Siddhartha</a>, by Hermann Hesse, a young prodigy of his tribe leaves his home and undertakes a long journey to gain spiritual enlightenment. In the process of knowing himself and the world, he loses himself. He goes against all the teachings of the elders of his tribe and everything he has always known. However, in the end, while not returning to his home, he returns in a state resembling his old state, but with hard-gained knowledge and wisdom. </div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"> This very idea of movie through space and time but coming back to a similar place, the notion of the cycles in life, of the cycles in Nature, is interesting to me. For a reason I can't explain, this is appealing to me. The idea that, through human history, through the succession of generations, I get to live forever. "At the still point of the turning world", through the center that must hold, where everyone is one and nothing, where the lonely streams become a river, the river of life, I can identify with everything. My "soul is the whole world". </div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div style="text-align: justify;"><span style="text-align: left;"> This is indeed very hard to explain. Even T.S. Eliot had problems expressing this idea:</span></div></div><blockquote class="tr_bq"><div style="text-align: justify;"> That was a way of putting it - not very satisfactory:</div><div style="text-align: justify;">A periphrastic study in a worn-out poetical fashion,</div><div style="text-align: justify;">Leaving one still with the intolerable wrestle</div><div style="text-align: justify;">With words and meanings. The poetry does not matter.</div></blockquote><div style="text-align: justify;">although the idea is, verily, quite simple. In a place, where there exists no time and no space, we are one. But not really.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"> This still point, being defined by the Universe, must be <i>of</i> the Universe. Imagine a rolling wheel. Its center does not move, being the center, but it must rotate as to accompany the wheel. We do not see it turning, but it must. We can relate this analogy to the conclusion of Siddhartha. <i>Carpe Diem</i>. Everything that is the world is beautiful; it must be appreciated and loved and such. Everything has sin and virtue in it.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"> But this isn't true. It is true only at the still point. What shall we do? Locally, then, an ethics system must be enforced. This ethical system, built by the people inhabiting the region of space and time by the means of logic and reason, must fulfill the requirements and principles of the people. </div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="text-align: left;"> Globally, this is my interpretation of this. Although I do not think the world completely deterministic, I believe that the entirety of possibilities is contained in the world. At the still point, then, the singularity of the Big Bang, every possible outcome exists and is as one; the future of the Universe is written as the wavefunction fo the Universe. At that time, the river breaks into a million pieces.</span></div><div style="text-align: justify;"><span style="text-align: left;"><br /></span></div><div style="text-align: justify;"><span style="text-align: left;"> What did I just say? I am confused. </span><span style="text-align: left;"> The poetry does not matter, but its equivocacy a way to expose without explaining, a way to confuse and inform. </span><br /><span style="text-align: left;"><br /></span><span style="text-align: left;"> This is it for now, but I shall return. </span></div></div>Joey Dumontme@joey-dumont.ca While sipping away at my alcoholic drink, I had, as men usually have, philosophical matters spring to my mind. Wrought body and soul in the shadow of the night, my first instinct was to share my thoughts with the world. In Siddhartha, by Hermann Hesse, a young prodigy of his tribe leaves his home and undertakes a long journey to gain spiritual enlightenment. In the process of knowing himself and the world, he loses himself. He goes against all the teachings of the elders of his tribe and everything he has always known. However, in the end, while not returning to his home, he returns in a state resembling his old state, but with hard-gained knowledge and wisdom. This very idea of movie through space and time but coming back to a similar place, the notion of the cycles in life, of the cycles in Nature, is interesting to me. For a reason I can't explain, this is appealing to me. The idea that, through human history, through the succession of generations, I get to live forever. "At the still point of the turning world", through the center that must hold, where everyone is one and nothing, where the lonely streams become a river, the river of life, I can identify with everything. My "soul is the whole world". This is indeed very hard to explain. Even T.S. Eliot had problems expressing this idea: That was a way of putting it - not very satisfactory:A periphrastic study in a worn-out poetical fashion,Leaving one still with the intolerable wrestleWith words and meanings. The poetry does not matter.although the idea is, verily, quite simple. In a place, where there exists no time and no space, we are one. But not really. This still point, being defined by the Universe, must be of the Universe. Imagine a rolling wheel. Its center does not move, being the center, but it must rotate as to accompany the wheel. We do not see it turning, but it must. We can relate this analogy to the conclusion of Siddhartha. Carpe Diem. Everything that is the world is beautiful; it must be appreciated and loved and such. Everything has sin and virtue in it. But this isn't true. It is true only at the still point. What shall we do? Locally, then, an ethics system must be enforced. This ethical system, built by the people inhabiting the region of space and time by the means of logic and reason, must fulfill the requirements and principles of the people. Globally, this is my interpretation of this. Although I do not think the world completely deterministic, I believe that the entirety of possibilities is contained in the world. At the still point, then, the singularity of the Big Bang, every possible outcome exists and is as one; the future of the Universe is written as the wavefunction fo the Universe. At that time, the river breaks into a million pieces. What did I just say? I am confused. The poetry does not matter, but its equivocacy a way to expose without explaining, a way to confuse and inform. This is it for now, but I shall return.