<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>The Eigenschlumpkin Herder</title>
    <description>Andrew Geng's blog, a space for notes on math and other subjects in slightly more depth than achieveable on social media sites.
</description>
    <link>http://pteromys.melonisland.net/w/</link>
    <atom:link href="http://pteromys.melonisland.net/w/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 21 Oct 2023 14:09:16 +0000</pubDate>
    <lastBuildDate>Sat, 21 Oct 2023 14:09:16 +0000</lastBuildDate>
    <generator>Jekyll v3.9.3</generator>
    
      <item>
        <title>Android Backups: A Yak Shave</title>
        <description>&lt;p itemprop=&quot;description&quot;&gt;The other day I finally got around to taking a backup of an ancient Nexus 7.
&lt;a href=&quot;https://android.stackexchange.com/a/28483&quot;&gt;A Stack Exchange answer by camalot&lt;/a&gt; lists a few methods
for turning it into plain files, so I go ahead and try the one that doesn&amp;rsquo;t
require me to download anything&amp;hellip;&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;1f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;8b&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;08&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; +25 ../clipper2.adb&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xvz&lt;/span&gt;
...
&lt;span class=&quot;nb&quot;&gt;gzip&lt;/span&gt;: stdin: unexpected end of file
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt;: Child returned status 1
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt;: Error is not recoverable: exiting now
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Uh-oh.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;the-device&quot;&gt;The device&lt;/h2&gt;

&lt;h3 id=&quot;loose-plugs-cause-bugs&quot;&gt;Loose plugs cause bugs&lt;/h3&gt;

&lt;p&gt;The first few tries, I didn&amp;rsquo;t even get the &amp;ldquo;Backup finished&amp;rdquo; toast notification
due to a loose USB cable. Turns out syslog messages like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB disconnect,
address 58&lt;/code&gt; indicate bad things when they&amp;rsquo;re timestamped suspiciously near the
backup file&amp;rsquo;s mtime. Who knew?&lt;/p&gt;

&lt;h3 id=&quot;adb-logcat&quot;&gt;adb logcat&lt;/h3&gt;

&lt;p&gt;But having solved that, did I still end up with a truncated file due to
some badness on the device? &lt;a href=&quot;https://github.com/nelenkov/android-backup-extractor/issues/49#issuecomment-412366371&quot;&gt;Apparently misbehaving apps can cause it&lt;/a&gt;.
Looking through the output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb logcat -s BackupManagerService&lt;/code&gt;, at first
things are pretty reassuring:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;09-17 23:28:16.568   656  1510 V BackupManagerService: Requesting full backup: apks=false obb=false shared=true all=true system=true pkgs=[Ljava.lang.String;@7c66c2f
...
09-17 23:38:48.689   656  3792 D BackupManagerService: Full backup pass complete.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Googling finds &lt;a href=&quot;https://talk.sonymobile.com/t5/Xperia-Z5-Z5-Compact-Z5-Premium/Sony-Xperia-Z5-Compact-fails-to-adb-backup-shared-storage/td-p/1136642&quot;&gt;users having problems with shared storage&lt;/a&gt;.
Hm, that log message wouldn&amp;rsquo;t have been captured by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s BackupManagerService&lt;/code&gt;,
so I try again with just the shared storage and indeed, there it is:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% adb backup &lt;span class=&quot;nt&quot;&gt;-shared&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /home/pteromys/clipper5.adb
% adb logcat
...
09-18 00:08:16.363 21132 21143 I FullBackup: Unrecognized domain shared/0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That looks beyond my ability to fix. Fortunately I&amp;rsquo;m not seeing any other
obvious problems in the log, so I just rerun the backup with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-noshared&lt;/code&gt;,
then pull the shared storage separately as plain files:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% adb backup &lt;span class=&quot;nt&quot;&gt;-all&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-noshared&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /home/pteromys/clipper6.adb
% adb pull /sdcard /home/pteromys/clipper-backup-sdcard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;when-your-tools-think-your-devices-are-too-old&quot;&gt;When your tools think your devices are too old&lt;/h3&gt;

&lt;p&gt;As I&amp;rsquo;m closing out the accumulated windows this catches my eye elsewhere in
the logs:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;09-17 23:42:25.840  8500  8500 D AndroidRuntime: Calling main entry com.android.commands.bu.Backup
09-17 23:42:25.841  8500  8500 D bu      : Beginning: help
09-17 23:42:25.842  8500  8500 E bu      : Invalid operation 'help'
09-17 23:42:25.842  8500  8500 D bu      : Finished.
09-17 23:42:25.842  8500  8500 D AndroidRuntime: Shutting down VM
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Riiiiight. So this was sort of a lie:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% adb help
...
backup/restore:
   to show usage run &quot;adb shell bu help&quot;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I&amp;rsquo;m guessing it&amp;rsquo;s because Nexus 7s stopped getting updates long before
&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/9d5f8e11e11e93fbf0d9cbcbb68b7b0062695e5d&quot;&gt;bu got its help message&lt;/a&gt; but I keep getting new releases of adb.&lt;/p&gt;

&lt;p&gt;Anyway, mission still accomplished, right? Close remaining windows, unplug the
USB cable, go to sleep, and finish this another day.&lt;/p&gt;

&lt;h2 id=&quot;the-file&quot;&gt;The file&lt;/h2&gt;

&lt;h3 id=&quot;the-zlib-file-format-according-to-pyflate&quot;&gt;The zlib file format according to pyflate&lt;/h3&gt;

&lt;p&gt;Would&amp;rsquo;ve been too easy if it had ended there, wouldn&amp;rsquo;t it? I get the same
gzip message on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clipper6.adb&lt;/code&gt; the next day. Maybe the zlib file format will
have some clues? &lt;a href=&quot;http://calmarius.net/?lang=en&amp;amp;page=programming%2Fzlib_deflate_quick_reference&quot;&gt;Calmarius&amp;rsquo;s guide to zlib + deflate&lt;/a&gt; explains that
it&amp;rsquo;s (modulo header and footer) just a concatenated stream of blocks. Awesome,
except&amp;hellip;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;blocks aren&amp;rsquo;t necessarily byte-aligned,&lt;/li&gt;
  &lt;li&gt;their boundaries are marked by an end-of-block symbol instead of listed
up front so you have to scan the file to find them, and&lt;/li&gt;
  &lt;li&gt;it&amp;rsquo;s Huffman encoded so you can&amp;rsquo;t find the end-of-block
symbol until you&amp;rsquo;ve decoded all the codewords before it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Still, if you can do it, you can test a hypothesis: maybe gzip expects more
because adb/bu didn&amp;rsquo;t bother to set the &amp;ldquo;this is the last block&amp;rdquo; bit on the
last block. Neither gzip nor python&amp;rsquo;s zlib module divulges this kind of
information about their internal state; but &lt;a href=&quot;https://github.com/pfalcon/pyflate&quot;&gt;pyflate&lt;/a&gt; will, and in
more detail than your most prolific friends on Facebook.&lt;/p&gt;

&lt;p&gt;Maybe hack out the parts that write the decompressed data to a file, though;
all we&amp;rsquo;re interested in is what it does to the end. And of course it&amp;rsquo;ll be
slower than gzip, so go find a snack or something. And eventually&amp;hellip;&lt;/p&gt;

&lt;h3 id=&quot;the-pyflate-output&quot;&gt;The pyflate output&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% python2 ~/.local/lib/python2/site-packages/pyflate.py =(echo -n '\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'; tail -c +27 /home/pteromys/clipper6.adb)
...
new block at (580253004, 0)
last bit 0x0
deflate-blocktype 0 stored beginning at (580253004, 0)
raw block data at (580253004, 3)
new block at (580253009, 0)
last bit 0x1
deflate-blocktype 1 static huff beginning at (580253009, 0)
raw block data at (580253009, 3)
raw data at (580253009, 3) bits 3
found symbol 0xa3 of len 8 mapping to 0x11d
reading 0 extra bits for len
found symbol 0x0 of len 5 mapping to 0x0
reading 0 extra bits for dist
dictionary lookup: length 258 copy -1 num bits 13 data '\x00...\x00'
found symbol 0xa3 of len 8 mapping to 0x11d
reading 0 extra bits for len
found symbol 0x0 of len 5 mapping to 0x0
reading 0 extra bits for dist
dictionary lookup: length 258 copy -1 num bits 13 data '\x00...\x00'
found symbol 0xa3 of len 8 mapping to 0x11d
reading 0 extra bits for len
found symbol 0x0 of len 5 mapping to 0x0
reading 0 extra bits for dist
dictionary lookup: length 258 copy -1 num bits 13 data '\x00...\x00'
found symbol 0x23 of len 8 mapping to 0x11c
reading 5 extra bits for len
found symbol 0x0 of len 5 mapping to 0x0
reading 0 extra bits for dist
dictionary lookup: length 250 copy -1 num bits 18 data '\x00...\x00'
found symbol 0x0 of len 7 mapping to 0x100
eos 0 count 0 bits 7
end of Huffman block encountered
this was the last block, time to leave (580253017, 3)
Traceback (most recent call last):
  File &quot;/home/pteromys/.local/lib/python2/site-packages/pyflate.py&quot;, line 678, in &amp;lt;module&amp;gt;
    _main()
  File &quot;/home/pteromys/.local/lib/python2/site-packages/pyflate.py&quot;, line 648, in _main
    out = gzip_main(field)
  File &quot;/home/pteromys/.local/lib/python2/site-packages/pyflate.py&quot;, line 629, in gzip_main
    final_length = b.readbits(32)
  File &quot;/home/pteromys/.local/lib/python2/site-packages/pyflate.py&quot;, line 71, in readbits
    self.needbits(n)
  File &quot;/home/pteromys/.local/lib/python2/site-packages/pyflate.py&quot;, line 37, in needbits
    self._more()
  File &quot;/home/pteromys/.local/lib/python2/site-packages/pyflate.py&quot;, line 62, in _more
    c = self._read(1)
  File &quot;/home/pteromys/.local/lib/python2/site-packages/pyflate.py&quot;, line 32, in _read
    raise &quot;Length Error&quot;
TypeError: exceptions must be old-style classes or derived from BaseException, not str
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-breakdown&quot;&gt;The breakdown&lt;/h3&gt;

&lt;p&gt;Here&amp;rsquo;s what we see in those last two blocks:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;An empty uncompressed block, which ends with its length marker &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0000ffff&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The next block starts with a 1 bit, so it was marked as the last block
after all. So much for that hypothesis.
    &lt;ul&gt;
      &lt;li&gt;Its contents are 258 + 258 + 258 + 250 = 1024 zeros, which
reassuringly is &lt;a href=&quot;https://en.wikipedia.org/wiki/Tar_(computing)#File_format&quot;&gt;how a tarball is supposed to end&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The end-of-block symbol gets read&amp;hellip; then what is it trying to read after
that?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The (zero-indexed) byte in which the empty block starts is 580253004 + 26
(bytes we chopped off with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tail&lt;/code&gt;) - 10 (bytes in the fake header we added) + 2
(bytes that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyflate.py&lt;/code&gt; skips before starting its count), which comes out
to 580253022. The file contents at this byte and forward are (recall &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tail&lt;/code&gt;
is 1-indexed):&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; +580253023 clipper6.adb | xxd
00000000: 0000 00ff ff1b 05a3 6014 8c5c 0000 df82  ........&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;..&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;...
00000010: f504                                     ..
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Decompressing that final block by hand is an educational experience, but
let&amp;rsquo;s skip that and pretend I trusted pyflate all along like I should have.&lt;/p&gt;

&lt;p&gt;The last message before the exception tells us that the end-of-block symbol
ends in the fifth-to-last byte, which leaves 4 bytes behind.
The &lt;a href=&quot;https://www.forensicswiki.org/wiki/Gzip#File_footer&quot;&gt;gzip footer&lt;/a&gt; is supposed to be 4 bytes of checksum
and 4 bytes of uncompressed data size; maybe the size is all we&amp;rsquo;re missing?
That would be very consistent with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;final_length = b.readbits(32)&lt;/code&gt; in
the traceback above&amp;hellip;&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;1f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;8b&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;08&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; +25 ../clipper6.adb&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; | zcat | &lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;gzip&lt;/span&gt;: stdin: unexpected end of file
3734081536

% python &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'print(&quot;%x&quot; % 3734081536)'&lt;/span&gt;
de919000

% &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;1f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;8b&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;08&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; +25 ../clipper6.adb&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;91&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;de&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; | zcat &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class=&quot;nb&quot;&gt;gzip&lt;/span&gt;: stdin: invalid compressed data--crc error
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok, I can live with that for now. Let&amp;rsquo;s just try one more time with a fake
size, to check that we really got the size right&amp;hellip;&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;% &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;1f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;8b&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;08&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; +25 ../clipper6.adb&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;91&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;df&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; | zcat &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class=&quot;nb&quot;&gt;gzip&lt;/span&gt;: stdin: invalid compressed data--crc error
&lt;span class=&quot;nb&quot;&gt;gzip&lt;/span&gt;: stdin: invalid compressed data--length error
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Yay.&lt;/p&gt;

</description>
        <pubDate>Sun, 14 Oct 2018 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2018/android-backups/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2018/android-backups/</guid>
        
        
      </item>
    
      <item>
        <title>git-annex DIY visual cribsheet</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://git-annex.branchable.com/&quot;&gt;git-annex&lt;/a&gt; lets git track files
and delegates the actual storage to some other backend
(plain files or a &amp;ldquo;special remote&amp;rdquo;). For your photo collection, you
probably just want the &lt;a href=&quot;https://git-annex.branchable.com/assistant/&quot;&gt;git-annex assistant&lt;/a&gt;.
But if not, here&amp;rsquo;s a cribsheet for everyday operations&amp;hellip;&lt;/p&gt;

&lt;h2 id=&quot;the-cribsheet&quot;&gt;The cribsheet&lt;/h2&gt;

&lt;figure&gt;
&lt;img alt=&quot;Some assembly required.&quot; title=&quot;Some assembly required.&quot; src=&quot;/w/up/git-annex.png&quot; itemprop=&quot;image&quot; /&gt;&lt;figcaption&gt;Some assembly required.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;&amp;hellip;and now you see why it&amp;rsquo;s do-it-yourself. So&amp;hellip;&lt;/p&gt;

&lt;p itemprop=&quot;description&quot;&gt;Copy this onto some scratch paper&lt;sup id=&quot;fnref:stickynote&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stickynote&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and skim through the
&lt;a href=&quot;https://git-annex.branchable.com/walkthrough/&quot;&gt;git-annex walkthrough&lt;/a&gt; for the command that each arrow
represents (a forked arrow counts as one arrow).
Use the thick orange arrows for your files
and the dotted purple arrows for the tracking info.
(And that purple dot next to &amp;ldquo;remotes&amp;rdquo; represents a copy of
the long purple arrow as a fork.)&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t be afraid to set up a test repo and remote somewhere in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp&lt;/code&gt;.
Later, when it&amp;rsquo;s time to create a repo for a real-world use case,
here are the quick hits&amp;hellip;&lt;/p&gt;

&lt;h2 id=&quot;setup-time-analysis-paralysis-for-a-real-repo&quot;&gt;Setup time analysis paralysis for a real repo&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global annex.genmetadata true&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;This automatically records the creation month of each file annexed.&lt;/li&gt;
      &lt;li&gt;For later reading: &lt;a href=&quot;http://git-annex.branchable.com/metadata/&quot;&gt;uses of metadata&lt;/a&gt; and &lt;a href=&quot;http://git-annex.branchable.com/tips/automatically_adding_metadata/&quot;&gt;autogenerating more metadata&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;For each remote: any &lt;a href=&quot;http://git-annex.branchable.com/encryption/&quot;&gt;encryption&lt;/a&gt;? (none, hybrid, or other?)
    &lt;ul&gt;
      &lt;li&gt;If yes, maybe you also want &lt;a href=&quot;http://git-annex.branchable.com/chunking/&quot;&gt;chunking&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Which hash to use: &lt;a href=&quot;http://git-annex.branchable.com/backends/&quot;&gt;annex.backend&lt;/a&gt; (set in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt;).
    &lt;ul&gt;
      &lt;li&gt;The default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SHA256E&lt;/code&gt; (SHA-2 of content and file extension) is probably fine.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:stickynote&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I&amp;rsquo;d suggest you do this on a sticky note on your monitor,
but sticky notes are kind of small. Anyway, it&amp;rsquo;s probably better if
you lose it next week and have to do this exercise a second time&amp;mdash;after
that, you&amp;rsquo;ll have it memorized for sure.&amp;nbsp;&lt;a href=&quot;#fnref:stickynote&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 14 Apr 2017 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2017/git-annex/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2017/git-annex/</guid>
        
        
      </item>
    
      <item>
        <title>Seven&amp;frac12; volumes of n-balls</title>
        <description>&lt;p&gt;In a pale imitation of the &lt;a href=&quot;http://web.mit.edu/~leonidus/www/Lecture8Problems.pdf&quot;&gt;Victor Guillemin style&lt;/a&gt;,
here are seven ways to calculate the volume of an n-ball,
in seven not-so-easy but somewhat spoiler-ful exercises.
What&amp;rsquo;s your favorite? And can you shed any light on
negative dimensions or the generating function in the last method?&lt;/p&gt;

&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;
&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#contents&quot; id=&quot;markdown-toc-contents&quot;&gt;Contents&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#elementary-inductions&quot; id=&quot;markdown-toc-elementary-inductions&quot;&gt;Elementary inductions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#multivariable-calculus-and-n-spheres&quot; id=&quot;markdown-toc-multivariable-calculus-and-n-spheres&quot;&gt;Multivariable calculus and n-spheres&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#without-integration&quot; id=&quot;markdown-toc-without-integration&quot;&gt;Without integration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#generating-functions&quot; id=&quot;markdown-toc-generating-functions&quot;&gt;Generating functions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#special-values-just-for-fun&quot; id=&quot;markdown-toc-special-values-just-for-fun&quot;&gt;Special values, just for fun&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;elementary-inductions&quot;&gt;Elementary inductions&lt;/h2&gt;

&lt;p&gt;If you weren&amp;rsquo;t satisfied with being confined to dimension 3
when you learned the formula \[ |D^3| = \frac{4}{3} \pi \]
for the volume of the unit 3-ball,
then I suspect you eventually figured out that you could:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 1&lt;/dt&gt;
  &lt;dd&gt;Integrate over a 2-disc and induct from dimensions 0 and 1.
(&lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Volume_of_an_n-ball&amp;amp;oldid=712881940#The_two-dimension_recursion_formula&quot;&gt;Walkthrough on Wikipedia&lt;/a&gt;)&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;If you were particularly bored in your calculus class,
maybe you challenged yourself to use only one base case:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 2&lt;/dt&gt;
  &lt;dd&gt;Starting from a 1-disc instead,
finish off the resulting integral with a
&lt;a href=&quot;https://en.wikibooks.org/wiki/Calculus/Integration_techniques/Trigonometric_Substitution&quot;&gt;trigonometric substitution&lt;/a&gt;
and a &lt;a href=&quot;https://en.wikibooks.org/wiki/Calculus/Integration_techniques/Reduction_Formula&quot;&gt;reduction formula&lt;/a&gt;.
(&lt;a href=&quot;http://www2.sjs.org/raulston/mvc.10/ISPs/Hyperspace.htm&quot;&gt;Walkthrough by Raulston&lt;/a&gt;)&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;multivariable-calculus-and-n-spheres&quot;&gt;Multivariable calculus and n-spheres&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a variant of Method 2 for the analogue of surface area,
in which you calculate
  \[ |S^{n+1}| = \int_{x=-1}^1 |S^n| (1-x^2)^{\frac{1}{2}n} \, ds \]
where \(ds = (1-x^2)^{-1/2} \, dx\)
is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Arc_length#Finding_arc_lengths_by_integrating&quot;&gt;element of arc length&lt;/a&gt;
for \(y = \sqrt{1-x^2}\).
This is halfway to a purely spherical-coordinates method,
which a little multivariable calculus lets you access:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 3&lt;/dt&gt;
  &lt;dd&gt;Carefully write down, in spherical coordinates,
the element of \(n\)-volume in the unit \(n\)-sphere
(the boundary \(S^n\) of the unit \((n+1)\)-ball).
Then integrate to find \(|S^n|\).
(&lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Volume_of_an_n-ball&amp;amp;oldid=712881940#Direct_integration_in_spherical_coordinates&quot;&gt;Walkthrough on Wikipedia&lt;/a&gt;,
using Beta functions instead of a reduction formula).&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Or if you were bored in a probability or stats class,
maybe you pulled some shenanigans with Gaussian integrals
and the radius coordinate:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 4&lt;/dt&gt;
  &lt;dd&gt;Using spherical symmetry, write
\(\left(\int_{-\infty}^{\infty} e^{-x^2} \, dx\right)^n\)
as a product of \(|S^{n-1}|\) and a 1-variable integral
that can be written as a value of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Gamma_function&quot;&gt;Gamma function&lt;/a&gt;.
Then compute its value for all \(n\)
by using polar coordinates in the case \(n=2\).
(&lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Volume_of_an_n-ball&amp;amp;oldid=712881940#Gaussian_integrals&quot;&gt;Walkthrough on Wikipedia&lt;/a&gt;)&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;A high-power variant of this method is to compute the Laplace transform
of \(f(y) = |D^n| y^{n/2} = \int_{|x|^2 \leq y} dx\)
and is &lt;a href=&quot;http://www.jstor.org/stable/2695624&quot;&gt;detailed by Lasserre (paywalled)&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;without-integration&quot;&gt;Without integration&lt;/h2&gt;

&lt;p&gt;Wikipedia&amp;rsquo;s a great source for these walkthroughs,
and it even includes mention of unit \(L^p\)-balls (with sources!).
But let&amp;rsquo;s go off the trail a little bit.
Our first stop goes way back&amp;mdash;to Archimedes&amp;rsquo;s
use of &lt;a href=&quot;https://en.wikipedia.org/wiki/Cavalieri%27s_principle&quot;&gt;Cavalieri&amp;rsquo;s principle&lt;/a&gt; to avoid
explicitly using calculus:&lt;/p&gt;

&lt;figure class=&quot;float right10&quot;&gt;
&lt;img alt=&quot;\(D^1 \times S^1\) is a cylindrical surface, the cone on which is a solid cylinder with two cones cut out.&quot; title=&quot;\(D^1 \times S^1\) is a cylindrical surface, the cone on which is a solid cylinder with two cones cut out.&quot; src=&quot;/w/up/archimedes-cone.png&quot; /&gt;&lt;figcaption&gt;\(D^1 \times S^1\) is a cylindrical surface, the cone on which is a solid cylinder with two cones cut out.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 5&lt;/dt&gt;
  &lt;dd&gt;Calculate that
over each point of \(D^n\), the 2-dimensional cross-sections of
\(D^{n+2}\) and the cone on \(D^n \times S^1\)
(with vertex at the origin) have the same area.
Then note that \(|S^1 \times X| = 2\pi |X|\)
and that passing to a height-1 cone divides volume by \(n+2\)
(i.e. the dimension of the ambient space).
(&lt;a href=&quot;http://www.jstor.org/stable/10.4169/amer.math.monthly.119.08.685&quot;&gt;Walkthrough by Makarov, paywalled&lt;/a&gt;)&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;As with Method 2, there&amp;rsquo;s an \(S^n\) variant that deserves mentioning.
(To recover the same recurrence as above,
use the fact that \(D^{n+2}\) is the cone on \(S^{n+1}\)
to relate their volumes.)&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 5&amp;frac12;&lt;/dt&gt;
  &lt;dd&gt;Calculate that
projecting to the equatorial disc \(f: S^n \to D^n\)
multiplies n-volume by a factor of \((1-|f(x)|^2)^{-1/2}\).
Since the \(S^1\)-shaped strip of \(S^{n+1}\) over \(f(x) \in D^n\)
has radius \((1-|f(x)|^2)^{1/2}\), conclude that
\(|S^{n+1}| = 2\pi|D^n|\).&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;If you&amp;rsquo;re willing to think only in even dimensions (i.e. \(D^{2n}\)),
here&amp;rsquo;s a super-cute method exploiting complex numbers
that I first heard of from my advisor:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 6&lt;/dt&gt;
  &lt;dd&gt;Let \((D^2)^n\) denote the product of unit discs in \(\mathbb{C}^n\)
(so its volume is \(\pi^n\)), and let
\(E = \{ 0 &amp;lt; |z_1| &amp;lt; \cdots &amp;lt; |z_n| &amp;lt; 1\} \subseteq (D^2)^n\)
be a fundamental domain under the action of permuting the coordinates.
Check that
\[ \begin{align*}
f: z &amp;amp;\mapsto w \in \mathbb{C}^n \\ 
w_1 &amp;amp;= z_1 \\ 
w_i &amp;amp;= z_i \sqrt{1 - \left| \frac{z_{i-1}}{z_i} \right|^2}
\end{align*} \]
defines a volume-preserving diffeomorphism from \(E\)
to a full-measure subset of \(D^{2n}\).
(&lt;a href=&quot;http://www.jstor.org/stable/2589320&quot;&gt;Walkthrough by Hijab, paywalled&lt;/a&gt;)&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;generating-functions&quot;&gt;Generating functions&lt;/h2&gt;

&lt;p&gt;Method 5&amp;frac12; produces the recurrence relation
\(|S^{n+1}| = 2\pi |D^n|\).
Generating functions are a tool for solving recurrence relations;
it&amp;rsquo;s overkill in this case, but you can do it:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 7&lt;/dt&gt;
  &lt;dd&gt;Let \( b(r) = \sum_{n=0}^\infty |D^n| r^n \).
Show that \(b&amp;rsquo;(r) = \sum_{n=0}^\infty |S^n| r^n\),
and use the recurrence above to conclude \(b&amp;rsquo; = 2 + 2\pi r b\).
This is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Linear_differential_equation#First-order_equation_with_variable_coefficients&quot;&gt;linear ODE&lt;/a&gt;; solve it to get
\[b(r) = e^{\pi r^2} \left(1 + 2\int_0^r e^{-\pi t^2}\, dt\right),\]
and expand it as a power series to recover the coefficients \(|D^n|\).
(&lt;a href=&quot;http://www.jstor.org/stable/2589319&quot;&gt;Walkthrough by Badger, paywalled&lt;/a&gt;)&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a href=&quot;http://www.johndcook.com/blog/2013/03/18/an-incomplete-post-about-sphere-volumes/&quot;&gt;Cook remarks&lt;/a&gt; that there ought to be some way to explain
the occurrence of the Gaussian in the formula for \(b(r)\);
you can get part of the way there with the following variant.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Method 7&amp;frac12;&lt;/dt&gt;
  &lt;dd&gt;The Laplace transform of \(f(x) = e^{-x^2}\) is
\[ \mathcal{L}\{f\}(y) = \int_0^\infty e^{-x^2} e^{-xy} \, dx . \]
Expand \(e^{-xy}\) as a power series,
and use the techniques of Method 4 to write the \(y^n\) coefficient
of \(\mathcal{L}\{f\}(y)\) in terms of \(|S^n|\).
(Yes, you can swap the integral and the sum since the sum
of integrals converges.)&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;The wrinkle here is that \(|S^n|\) ends up
in the &lt;em&gt;denominators&lt;/em&gt; of the coefficients,
while a substitution in the formula for \(b(r)\) shows that
  \[ b(r) = \mathcal{L}\{x \mapsto e^{-\pi x}\}(-2\pi r) . \]
Alas, I don&amp;rsquo;t see how to get more directly from this Laplace transform
to \(b(r)\); but on the bright side, equating the coefficients
in the two variants provides a roundabout way of proving
the Gamma function&amp;rsquo;s &lt;a href=&quot;https://en.wikipedia.org/wiki/Gamma_function#Properties&quot;&gt;duplication formula&lt;/a&gt; at integers,
  \[ \Gamma(n)\Gamma\left(n+\frac{1}{2}\right) =
  2^{1-2n} \sqrt{\pi} \, \Gamma(2n) . \]&lt;/p&gt;

&lt;h2 id=&quot;special-values-just-for-fun&quot;&gt;Special values, just for fun&lt;/h2&gt;

&lt;p&gt;Trivial coefficients occur with \(|D^0| = 1\), \(|D^2| = \pi\),
and \(|S^5| = \pi^3\), which makes me think the Raspberry Pi
Foundation missed a minor branding opportunity earlier this year.
Or if you&amp;rsquo;re a &lt;a href=&quot;http://tauday.com/&quot;&gt;tauist&lt;/a&gt;, you also get \(|S^1| = \tau\).
For something approaching a tauist spiritual experience,
&lt;a href=&quot;#elementary-inductions&quot; onclick=&quot;var jax = MathJax.Hub.getAllJax(document.getElementsByTagName('article')[0]); for (var i = 0; i &amp;lt; jax.length; i++) { jax[i].SourceElement().innerHTML = jax[i].originalText.replace('4}{3} \\pi', '2}{3}|S^1|').replace('1-2n} \\sqrt{\\pi', '-2n} \\sqrt{|S^1|').replace(/2\\pi/g, '|S^1|').replace(/\\pi\^/g, '\\left(\\frac{1}{2}|S^1|\\right)^').replace(/\\pi/g, '\\frac{1}{2}|S^1|'); } MathJax.Hub.Queue(['Reprocess', MathJax.Hub]); return true;&quot;&gt;go back and replace all
occurrences of \(\pi\) with \(\frac{1}{2}|S^1|\)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Maybe you noticed that the Gamma function is still defined at
negative half-integers, which goads you into asking whether
  \[ |S^{-2}| = \frac{2 \pi^{\frac{-2+1}{2}}}{\Gamma\left(\frac{-2+1}{2}\right)} = -\frac{1}{\pi} \]
has any meaning. Despite having stumbled over negative-dimensional
spheres in a quest to convince myself that
&lt;a href=&quot;http://arxiv.org/abs/math.CT/0608420&quot;&gt;(-2)-categories are a thing&lt;/a&gt;,
I&amp;rsquo;m leaning toward: &lt;a href=&quot;http://math.stackexchange.com/questions/423874/&quot;&gt;probably not&lt;/a&gt;&amp;mdash;at least,
not in any sense that looks obviously to me like a
&lt;a href=&quot;http://math.stackexchange.com/questions/1176034/&quot;&gt;moral analogue of volume&lt;/a&gt;.
But if you&amp;rsquo;ve got ideas, I&amp;rsquo;m listening.&lt;/p&gt;

</description>
        <pubDate>Wed, 01 Jun 2016 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2016/balls/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2016/balls/</guid>
        
        <category>math</category>
        
        
      </item>
    
      <item>
        <title>Simplicial whatever quickstart guide</title>
        <description>&lt;p&gt;Simplicial sets are useful for&amp;hellip; okay, I really have no idea what.
I just got sucked into reading about them.
Of many available references,
I enthusiastically recommend &lt;a href=&quot;http://arxiv.org/abs/0809.4221&quot;&gt;Friedman&amp;rsquo;s notes&lt;/a&gt;;
the quality of exposition is totally unparalleled.
The following are merely my notes on the differences between
simplicial complexes, delta complexes, and simplicial sets.&lt;/p&gt;

&lt;h2 id=&quot;complexes&quot;&gt;Complexes&lt;/h2&gt;

&lt;figure class=&quot;float right10&quot;&gt;
&lt;img alt=&quot;A 3-D simplex.&quot; title=&quot;A 3-D simplex.&quot; src=&quot;/w/up/simplex.png&quot; /&gt;&lt;figcaption&gt;A 3-D simplex.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;So you want to jam simplices together to make shapes.
Maybe you&amp;rsquo;re building a 3-D model out of triangles for a video game.
Because we attempt to understand things via their sub-things,
the following assumptions are convenient,
and thus shared by all the complexes we&amp;rsquo;re about to discuss:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Each simplex comes with all its sub-simplices
  (itself, faces, vertices, etc), and&lt;/li&gt;
  &lt;li&gt;The intersection of simplices is always a union of their sub-simplices.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;simplicial-complexes&quot;&gt;Simplicial complexes&lt;/h2&gt;

&lt;p&gt;To recover the definition of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Simplicial_complex&quot;&gt;simplicial complex&lt;/a&gt;,
just require:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Additional assumption for simplicial complexes&lt;/dt&gt;
  &lt;dd&gt;Each simplex can be specified uniquely by the set of its vertices.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;This is a union of simplices in the nicest way possible;
and video game model formats such as &lt;a href=&quot;https://en.wikipedia.org/wiki/MD2_(file_format)&quot;&gt;MD2&lt;/a&gt;
actually specify their simplices as lists of vertices.&lt;/p&gt;

&lt;h2 id=&quot;delta-complexes&quot;&gt;Delta complexes&lt;/h2&gt;

&lt;p&gt;Sometimes you want to do more than play video games.
It being May, maybe you wanted to pick some flowers.&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;A flower, not colored in.&quot; title=&quot;A flower, not colored in.&quot; src=&quot;/w/up/wedge-five-circles.png&quot; class=&quot;grayscale-invertible&quot; /&gt;&lt;figcaption&gt;A flower, not colored in.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;This is still made of simplices
(a point and some (curved) line segments);
but a set of vertices no longer determines the simplex.
We attempt a generalization:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Delta complex data model&lt;/dt&gt;
  &lt;dd&gt;For each simplex, list not just the 0-subsimplices,
but &lt;em&gt;all&lt;/em&gt; the subsimplices.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Then the above flower can be specified with the following information:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a point \(P\);&lt;/li&gt;
  &lt;li&gt;five line segments \(a\), \(b\), \(c\), \(d\), and \(e\); and&lt;/li&gt;
  &lt;li&gt;the left endpoint of \(a\) is \(P\) and so is the right endpoint;&lt;/li&gt;
  &lt;li&gt;&amp;hellip;and similarly for the other four line segments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;organizing-the-delta-complex-data-model&quot;&gt;Organizing the delta complex data model&lt;/h2&gt;

&lt;h3 id=&quot;data-needed-to-describe-the-flower-above&quot;&gt;Data needed to describe the flower above&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;A set of 0-simplices (points)&lt;/li&gt;
  &lt;li&gt;A set of 1-simplices (line segments)&lt;/li&gt;
  &lt;li&gt;A &amp;ldquo;left endpoint function&amp;rdquo; taking 1-simplices to 0-simplices&lt;/li&gt;
  &lt;li&gt;A &amp;ldquo;right endpoint function&amp;rdquo;, similarly&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;in-higher-dimensions&quot;&gt;In higher dimensions&lt;/h3&gt;

&lt;p&gt;From the 2-simplices we&amp;rsquo;d need 3 edge maps and 3 vertex maps,
along with some compatibility conditions
like how some vertices of some edges are vertices of some other edges&amp;mdash;in
other words, the subsimplex functions have to compose the same way
they do in a typical simplex. If we call that
a &amp;ldquo;reference simplex&amp;rdquo; and encode it as a category
\(\widehat{\Delta}^{\mathrm{op}}\)
that looks like this:&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;The reference simplex.&quot; title=&quot;The reference simplex.&quot; src=&quot;/w/up/delta-op-category.png&quot; class=&quot;grayscale-invertible&quot; /&gt;&lt;figcaption&gt;The reference simplex.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;&amp;hellip;then we can define a delta complex to be a functor from
\(\widehat{\Delta}^{\mathrm{op}}\)
to the category of sets.&lt;/p&gt;

&lt;h3 id=&quot;recovering-the-usual-definition-of-widehatdelta&quot;&gt;Recovering the usual definition of \(\widehat{\Delta}\)&lt;/h3&gt;

&lt;p&gt;A subsimplex of the reference simplex &lt;em&gt;is&lt;/em&gt; determined
by the set of its vertices; so the arrows in
\(\widehat{\Delta}^{\mathrm{op}}\)
can be expressed by reversing inclusions of sets of vertices.
Then it&amp;rsquo;s just a matter of realizing that we can make there be
exactly one arrow per face inclusion by ordering the vertices
and requiring the set inclusions to be increasing functions.&lt;/p&gt;

&lt;h2 id=&quot;simplicial-sets&quot;&gt;Simplicial sets&lt;/h2&gt;

&lt;figure class=&quot;float right10&quot;&gt;
&lt;img alt=&quot;Making a degenerate 3-simplex.&quot; title=&quot;Making a degenerate 3-simplex.&quot; src=&quot;/w/up/simplex-degenerate.png&quot; /&gt;&lt;figcaption&gt;Making a degenerate 3-simplex.&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;To go from Delta complexes to simplicial sets is to allow
&amp;ldquo;degenerate simplices&amp;rdquo;&amp;mdash;simplices that have secretly collapsed
down to a lower dimension.
This is encoded as a category
\(\Delta\), obtained from \(\widehat{\Delta}\)
by replacing &amp;ldquo;increasing&amp;rdquo; with &amp;ldquo;nondecreasing&amp;rdquo;.
Significant consequences of this minor-looking change include:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Every simplex now comes with all its possible degeneracies.
  So that nice triangle mesh from your favorite video game
  becomes full of squashed 3-simplices
  and 4-simplices and 5-simplices and&amp;hellip;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;On the bright side, those degenerate simplices make it possible
  to define products of simplicial sets in a way that looks too good
  to be true.
  A good picture of why it works is in Chapter 5 of Friedman&amp;rsquo;s notes;
  but I have to leave it to you to come up with a pithy colloquial
  explanation that you personally find satisfying.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;dl&gt;
  &lt;dt&gt;Exercise&lt;/dt&gt;
  &lt;dd&gt;As simplicial sets, how does the flower in Figure 2 differ from
a point? (That is, what property of the degeneracy function from
0-simplices to 1-simplices distinguishes them?)&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;whats-still-missing&quot;&gt;What&amp;rsquo;s still missing&lt;/h2&gt;

&lt;p&gt;Geometry textbooks are full of wacky instructions like
&amp;ldquo;glue this face to that face with an \(x\)-degree twist&amp;rdquo;;
but there&amp;rsquo;s no freedom to do so on the faces of a simplex&amp;mdash;each face
comes with an ordering of its vertices,
which determines the only way they can be glued together.
Even degeneracies don&amp;rsquo;t help, owing to the &amp;ldquo;nondecreasing&amp;rdquo; condition.&lt;/p&gt;

&lt;p&gt;Really, we shouldn&amp;rsquo;t expect
simplicial sets to allow arbitrary reordering when gluing faces together.
That would allow gluing a face of a face to itself with arbitrary
reordering&amp;mdash;which amounts to taking a quotient by
some subgroup of permutations of vertices.
If you need that kind of flexibility,
it&amp;rsquo;s probably time to invoke good ol&amp;rsquo; &lt;a href=&quot;https://en.wikipedia.org/wiki/Barycentric_subdivision&quot;&gt;barycentric subdivision&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Wed, 25 May 2016 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2016/simplicial/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2016/simplicial/</guid>
        
        <category>math</category>
        
        
      </item>
    
      <item>
        <title>A survey of underlines in HTML</title>
        <description>&lt;p&gt;So I was preparing my résumé the other day, because it&amp;rsquo;s job season.
Something sounded elegant about having it in a texty format like LaTeX or HTML.
Since the LaTeX community contains
&lt;a href=&quot;/w/2015/underlines/#prescriptivism&quot;&gt;a few too many prescriptivists for my taste&lt;/a&gt;,
HTML it was.
Soon, having learned fascinating nuggets like
&lt;a href=&quot;http://stackoverflow.com/questions/5709698/&quot;&gt;how reluctant browsers are to do subpixel drawing&lt;/a&gt;,
I began to regret not using this as an excuse to learn Scribus.&lt;/p&gt;

&lt;p&gt;But as much as I would love to tell you about my regrets,
I meant instead to write a post about drawing pretty underlines.
Check out the way Epiphany&amp;rsquo;s underline skips the descender on the &amp;ldquo;p&amp;rdquo;:&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;Chrome 46 (left) vs. Epiphany 3.18 (right)&quot; title=&quot;Chrome 46 (left) vs. Epiphany 3.18 (right)&quot; src=&quot;/w/up/underlines.png&quot; itemprop=&quot;image&quot; /&gt;&lt;figcaption&gt;Chrome 46 (left) vs. Epiphany 3.18 (right)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;native-support-in-browsers&quot;&gt;Native support in browsers&lt;/h2&gt;

&lt;p&gt;It turns out that a &lt;a href=&quot;http://www.w3.org/TR/2013/CR-css-text-decor-3-20130801/#text-decoration-skip-property&quot;&gt;text-decoration-skip:ink&lt;/a&gt;
has been in a Candidate Recommendation since August 2013.
There&amp;rsquo;s no support yet in &lt;del&gt;&lt;a href=&quot;https://code.google.com/p/chromium/issues/detail?id=477917&quot;&gt;Chrome&lt;/a&gt; or&lt;/del&gt;&lt;sup id=&quot;fnref:ChromeFixed&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ChromeFixed&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=812990&quot;&gt;Gecko&lt;/a&gt;;
but in November 2013, only seven months after
&lt;a href=&quot;https://groups.google.com/a/chromium.org/d/msg/blink-dev/J41PSKuMan0/gD5xcqicqP8J&quot;&gt;Blink forked from WebKit&lt;/a&gt;,
support &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=121806&quot;&gt;landed in WebKit&lt;/a&gt;.
The following January,
&lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=127331&quot;&gt;it got made the default&lt;/a&gt;&amp;mdash;in time for the
release of iOS 8 and Safari 8 that fall.&lt;/p&gt;

&lt;p&gt;I haven&amp;rsquo;t been able to find the discussion of why
this was the right thing to do.
In fact, Comment 11 in that last link noted that the change deviates from
the specification, provoking &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=128723&quot;&gt;a so-far-unfinished effort&lt;/a&gt;
to follow the spec more closely. But given the enthusiasm with which
the change was embraced by observers of iOS 8, it may be here to stay.&lt;/p&gt;

&lt;h2 id=&quot;non-native-implementations-and-line-thickness&quot;&gt;Non-native implementations and line thickness&lt;/h2&gt;

&lt;p&gt;Back in early 2014, descender-skipping was a part of
Marcin Wichary&amp;rsquo;s &lt;a href=&quot;https://medium.com/designing-medium/crafting-link-underlines-on-medium-7c03a9274f9&quot;&gt;tremendous effort on underlines at Medium&lt;/a&gt;
that included work to control the thickness of underlines.
(Despite &lt;a href=&quot;http://www.acusti.ca/blog/2014/11/28/towards-a-more-perfect-link-underline/&quot;&gt;a noticeable need for thin underlines in light font-weights&lt;/a&gt;,
support for controlling line thickness is nonexistent
&lt;a href=&quot;http://www.w3.org/TR/2013/CR-css-text-decor-3-20130801/#text-decoration-skip-property&quot;&gt;in the spec&lt;/a&gt; and &lt;a href=&quot;https://code.google.com/p/chromium/issues/detail?id=338148&quot;&gt;in browsers&lt;/a&gt;.
And if you searched for such on Google, this may also be an opportunity to
lament how quickly HTML answers become dated
on Stack Overflow&amp;mdash;&lt;a href=&quot;http://stackoverflow.com/questions/13840403/&quot;&gt;like this one&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Though the skipping part was dropped from Wichary&amp;rsquo;s final version,
the technique of using a gradient background and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-shadow&lt;/code&gt;
has inspired a number of other implementations, including at least
two libraries you could use:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://eager.io/showcase/SmartUnderline/&quot;&gt;Adam Schwartz&amp;rsquo;s SmartUnderline&lt;/a&gt;
covers descender-skipping and line thickness
with no effort on your part.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wentin/underlineJS&quot;&gt;Wenting Zhang&amp;rsquo;s Canvas-powered UnderlineJS&lt;/a&gt;
is carefully thought out, down to the sizes of the holes around descenders.
And the live demo makes sounds!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;obstacles-to-adoption&quot;&gt;Obstacles to adoption&lt;/h2&gt;

&lt;p&gt;First, skipping descenders might not actually be the right move;
going against the grain of iOS,
&lt;a href=&quot;http://ilyabirman.net/meanwhile/all/underlines-and-descenders/&quot;&gt;Ilya Birman argues for thin, uninterrupted link underlines&lt;/a&gt;
on semantic grounds.
A &lt;a href=&quot;https://news.ycombinator.com/item?id=8587078&quot;&gt;thread on HN&lt;/a&gt;
indicates a number of commenters share this viewpoint
(and also points out possible prior art by Roman Komarov).&lt;/p&gt;

&lt;p&gt;Meanwhile, I&amp;rsquo;m a little bothered by how much closer the &amp;ldquo;o&amp;rdquo; is to the
&amp;ldquo;m&amp;rdquo; than the &amp;ldquo;t&amp;rdquo; in Epiphany&amp;rsquo;s rendering of &amp;ldquo;motions&amp;rdquo;.
Maybe that&amp;rsquo;s just because I&amp;rsquo;m used to looking at Chrome;
but until I learn more about kerning,
I guess I&amp;rsquo;m sticking with using Chrome to render my résumé to PDF.&lt;/p&gt;

&lt;p&gt;Still, I&amp;rsquo;ll keep the above in mind in case I ever need to
underline mathematical formulas with subscripts.
Somehow my handwritten notes are full of such,
while the concept has never even occurred to me for typeset math.
(There&amp;rsquo;s a good chance it&amp;rsquo;s a bad idea.)&lt;/p&gt;

&lt;h2 id=&quot;prescriptivism&quot;&gt;A footnote on LaTeX and prescriptivism&lt;/h2&gt;

&lt;p&gt;Okay, it&amp;rsquo;s not really the prescriptivism that I mind
so much as the total lack of interest in justifying prescriptions.
&lt;a href=&quot;http://tex.stackexchange.com/questions/1583/&quot;&gt;For example&lt;/a&gt;: despite widespread knowledge that
footnotes in tables are considered bad style,
(1) nobody seems to know why, and
(2) there&amp;rsquo;s a profusion of implementations.
Do these seem causally related to you?&lt;/p&gt;

&lt;p&gt;Admittedly, the OP was probably unwise to put two questions in one post,
since accepting an answer for #2 made #1 all but invisible.
And on the bright side, &lt;a href=&quot;http://comments.gmane.org/gmane.mail.postfix.user/196733&quot;&gt;it could have been less civil&lt;/a&gt;.
(Then again, the postfix thread has a happy ending,
which the SE thread can&amp;rsquo;t quite claim.)&lt;/p&gt;

&lt;h2 id=&quot;updates&quot;&gt;Updates&lt;/h2&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:ChromeFixed&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Chrome support was added
on &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=649700&quot;&gt;November 19, 2016&lt;/a&gt;.&amp;nbsp;&lt;a href=&quot;#fnref:ChromeFixed&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 09 Nov 2015 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2015/underlines/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2015/underlines/</guid>
        
        <category>history</category>
        
        
      </item>
    
      <item>
        <title>What is a quasicrystal?</title>
        <description>&lt;p&gt;This post was originally a talk given in &lt;a href=&quot;http://math.uchicago.edu/~pizzaseminar/&quot;&gt;Pizza Seminar&lt;/a&gt;
on October 15, 2014. Most of the mathematical content is from
Wikipedia and &lt;a href=&quot;http://iopscience.iop.org/0305-4470/22/2/009&quot;&gt;this paper by Niizeki&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;
&lt;p itemprop=&quot;description&quot;&gt;The crystallographic restriction theorem
says a finite-order automorphism of \(\mathbb{Z}^3\)
(in chemistry language, a symmetry of a crystal)
has order 1, 2, 3, 4, or 6.
But \(\mathbb{Z}^3\) is small potatoes; so let&amp;rsquo;s go to \(\mathbb{Z}^n\),
do some Galois theory in cyclotomic fields,
and get us some icosahedral symmetry!
(Icosahedrite is a real thing, say serious scientists.)
Pretty pictures will be provided, including demonstrations of self-similarity.
Self-similarity is always cool, right?&lt;/p&gt;

&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;
&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abstract&quot; id=&quot;markdown-toc-abstract&quot;&gt;Abstract&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#contents&quot; id=&quot;markdown-toc-contents&quot;&gt;Contents&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-crystallographic-restriction-theorem&quot; id=&quot;markdown-toc-the-crystallographic-restriction-theorem&quot;&gt;The crystallographic restriction theorem&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#x-ray-crystallography-peeking-inside-real-crystals&quot; id=&quot;markdown-toc-x-ray-crystallography-peeking-inside-real-crystals&quot;&gt;X-ray crystallography: peeking inside real crystals&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#setup&quot; id=&quot;markdown-toc-setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#a-troublesome-photo&quot; id=&quot;markdown-toc-a-troublesome-photo&quot;&gt;A troublesome photo&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#demo-making-waves&quot; id=&quot;markdown-toc-demo-making-waves&quot;&gt;Demo: Making waves&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#slicing-higher-dimensional-lattices&quot; id=&quot;markdown-toc-slicing-higher-dimensional-lattices&quot;&gt;Slicing higher-dimensional lattices&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#the-problem-locating-atoms&quot; id=&quot;markdown-toc-the-problem-locating-atoms&quot;&gt;The problem: locating atoms&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#the-explicit-recipe&quot; id=&quot;markdown-toc-the-explicit-recipe&quot;&gt;The explicit recipe&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#demo-atoms-in-2-d-quasicrystals&quot; id=&quot;markdown-toc-demo-atoms-in-2-d-quasicrystals&quot;&gt;Demo: Atoms in 2-D quasicrystals&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#self-similarity&quot; id=&quot;markdown-toc-self-similarity&quot;&gt;Self-similarity&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#a-number-theoretic-model-of-quasicrystals&quot; id=&quot;markdown-toc-a-number-theoretic-model-of-quasicrystals&quot;&gt;A number-theoretic model of quasicrystals&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#a-mathematical-description-of-zooming&quot; id=&quot;markdown-toc-a-mathematical-description-of-zooming&quot;&gt;A mathematical description of zooming&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#3-d-quasicrystals&quot; id=&quot;markdown-toc-3-d-quasicrystals&quot;&gt;3-D quasicrystals&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#the-n-dimensional-viewpoint&quot; id=&quot;markdown-toc-the-n-dimensional-viewpoint&quot;&gt;The n-dimensional viewpoint&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#the-search-for-3-d-quasicrystals&quot; id=&quot;markdown-toc-the-search-for-3-d-quasicrystals&quot;&gt;The search for 3-D quasicrystals&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#footnotes&quot; id=&quot;markdown-toc-footnotes&quot;&gt;Footnotes&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;!-- TODO: style this TOC --&gt;

&lt;h2 id=&quot;the-crystallographic-restriction-theorem&quot;&gt;The crystallographic restriction theorem&lt;/h2&gt;

&lt;p&gt;A crystal is a regular grid (like \(\mathbb{Z}^3\)) of atoms.
There is a remarkable theorem about what symmetries a crystal can admit:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Theorem (crystallographic restriction theorem)&lt;/dt&gt;
  &lt;dd&gt;If \(A \in \operatorname{Aut} \mathbb{Z}^3\) has finite order,
then the order is 1, 2, 3, 4, or 6.&lt;/dd&gt;
  &lt;dt&gt;Proof&lt;/dt&gt;
  &lt;dd&gt;Properties of \(A\) imply properties of its eigenvalues:

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;\(A\)&lt;/th&gt;
          &lt;th&gt;eigenvalues&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;finite order&lt;/td&gt;
          &lt;td&gt;on the unit circle \(S^1\)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;real&lt;/td&gt;
          &lt;td&gt;in complex conjugate pairs (so one is \(\pm 1\))&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;integer&lt;/td&gt;
          &lt;td&gt;their sum, \(\operatorname{tr} A\), is an integer&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;So if \(e^{i\theta}\) is an eigenvalue of \(A\), then
\[ \operatorname{tr} A = e^{i\theta} + e^{-i\theta} \pm 1 = 2 \cos \theta \pm 1. \]
Therefore \(\cos \theta \in \frac{1}{2} \mathbb{Z}\).
The eigenvalues \(e^{i\theta}\) satisfying this
are of order 1, 2, 3, 4, and 6.&lt;/p&gt;

    &lt;figure&gt;
&lt;img alt=&quot;Eigenvalues on the unit circle with half-integer real part&quot; title=&quot;Eigenvalues on the unit circle with half-integer real part&quot; src=&quot;/w/up/half-integers.png&quot; class=&quot;grayscale-invertible&quot; /&gt;&lt;figcaption&gt;Eigenvalues on the unit circle with half-integer real part&lt;/figcaption&gt;&lt;/figure&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;x-ray-crystallography-peeking-inside-real-crystals&quot;&gt;X-ray crystallography: peeking inside real crystals&lt;/h2&gt;

&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;/h3&gt;

&lt;p&gt;Here&amp;rsquo;s how scientists figure out the internal structure of a crystal.
To start, shine an x-ray on it and record the scattered radiation on film.
For our purposes, an x-ray is a function \(f\) satisfying
	\[ f(x+?) = e^{i k \cdot x} f(?) \]
for some vector \(k\) that depends on the ray direction and wavelength.
This lets us calculate the factors by which \(f\) changes
from source \(x_1\) to atom \(x\) and from atom to film \(x_2\).&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;X-rays bouncing off an atom&quot; title=&quot;X-rays bouncing off an atom&quot; src=&quot;/w/up/scattering.png&quot; class=&quot;grayscale-invertible&quot; /&gt;&lt;figcaption&gt;X-rays bouncing off an atom&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The total change in \(f\) is by a factor of
\( e^{i[(k_1 - k_2) \cdot x - k_1 \cdot x_1 + k_2 \cdot x_2]} . \)
Integrating this over all atom positions \(x\) in the crystal
yields the total radiation bounced in the direction of \(k_2\).
So&amp;hellip;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Upshot&lt;/dt&gt;
  &lt;dd&gt;The photo records (part of)
the Fourier transform of the distribution of atoms.&lt;sup id=&quot;fnref:phaseRecovery&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:phaseRecovery&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3 id=&quot;a-troublesome-photo&quot;&gt;A troublesome photo&lt;/h3&gt;

&lt;p&gt;Since rotational symmetries of a lattice are inherited by
its Fourier transform, photos like the one below
would seem to violate the crystallographic restriction theorem.&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;X-ray photo with order 10 symmetry&quot; title=&quot;X-ray photo with order 10 symmetry&quot; src=&quot;/w/up/diffraction.jpg&quot; /&gt;&lt;figcaption&gt;X-ray photo with order 10 symmetry&lt;br /&gt;by Materialscientist &lt;a href=&quot;http://commons.wikimedia.org/wiki/File:Zn-Mg-HoDiffraction.JPG&quot;&gt;on Wikimedia Commons&lt;/a&gt; (CC-BY-SA-3.0)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&quot;demo-making-waves&quot;&gt;Demo: Making waves&lt;/h3&gt;

&lt;p&gt;To get a picture of what kind of crystal we&amp;rsquo;re looking at,
let&amp;rsquo;s approximate the inverse transform by adding waves at
\(n\) regularly spaced angles. Try it for 5, 8, 12, and 7.&lt;/p&gt;

&lt;div class=&quot;demo-link&quot;&gt;&lt;a href=&quot;/quasi/waves.html&quot;&gt;&lt;img alt=&quot;Thumbnail&quot; src=&quot;/quasi/thumb-waves.jpg&quot; /&gt;&lt;span class=&quot;demo-text&quot;&gt;Demo&lt;br /&gt;Sums of waves&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;You can &lt;a href=&quot;http://mainisusuallyafunction.blogspot.com/2011/10/quasicrystals-as-sums-of-waves-in-plane.html&quot;&gt;animate these too&lt;/a&gt;; and
Jason Davies has a &lt;a href=&quot;http://www.jasondavies.com/animated-quasicrystals/&quot;&gt;WebGL adaptation&lt;/a&gt;
of the animation.&lt;/p&gt;

&lt;h2 id=&quot;slicing-higher-dimensional-lattices&quot;&gt;Slicing higher-dimensional lattices&lt;/h2&gt;

&lt;h3 id=&quot;the-problem-locating-atoms&quot;&gt;The problem: locating atoms&lt;/h3&gt;

&lt;p&gt;The last demo showed you the graph of
\(f(x) = \displaystyle\sum_{i=1}^n \cos (k_i \cdot x) \)
in \(\mathbb{R}^2\) for evenly spaced \(k_i\) on the unit circle.
This is all very nice and smooth,
but we want to actually place atoms&amp;mdash;discrete points&amp;mdash;in a grid.
Let&amp;rsquo;s put them in the hotspots&amp;mdash;i.e. where \(f\) hits some threshold.&lt;/p&gt;

&lt;p&gt;To turn this into a discrete process, use the following trick:
realize the waves \(\cos (k_i \cdot x)\) as 2-D slices of independent
waves in \(\mathbb{R}^n\)&amp;mdash;then hotspots are where the slice passes
near lattice points.&lt;/p&gt;

&lt;h3 id=&quot;the-explicit-recipe&quot;&gt;The explicit recipe&lt;/h3&gt;

&lt;p&gt;Let \(f\) be the restriction of the function
  \[ \mathbb{R}^n \ni x \mapsto \sum_{i=1}^n \cos (e_i \cdot x) \]
to a 2-plane on which the basis vectors \(e_i\) project to \(k_i\).
To choose the 2-plane, let \(A \in \operatorname{GL}_n \mathbb{Z}\)
act by cycling the basis vectors \(e_i\).
Diagonalizing over \(\mathbb{C}\) gets you the matrix
  \[ \begin{pmatrix} \zeta &amp;amp; &amp;amp; &amp;amp; &amp;amp; \\ &amp;amp; \zeta^{-1} &amp;amp; &amp;amp; &amp;amp; \\ &amp;amp; &amp;amp; \zeta^2 &amp;amp; &amp;amp; \\ &amp;amp; &amp;amp; &amp;amp; \zeta^{-2} &amp;amp; \\ &amp;amp; &amp;amp; &amp;amp; &amp;amp; \ddots \end{pmatrix} \]
where \(\zeta = e^{2 \pi i / n}\). Over \(\mathbb{R}\),
the eigenvalues pair into 2&amp;times;2 blocks,
corresponding to 2-planes on which \(A\)
acts as rotation by a multiple of \(\frac{2\pi}{n}\).
Pick any one of them.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Upshot&lt;/dt&gt;
  &lt;dd&gt;
    &lt;ul&gt;
      &lt;li&gt;The 2-plane is a 2-dimensional subrepresentation \(V\) of
\(\langle A \rangle \curvearrowright \mathbb{R}^n\).&lt;/li&gt;
      &lt;li&gt;Atoms (hotspots) are
points of \(V\) that lie kinda near points of \(\mathbb{Z}^n\).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;h3 id=&quot;demo-atoms-in-2-d-quasicrystals&quot;&gt;Demo: Atoms in 2-D quasicrystals&lt;/h3&gt;

&lt;p&gt;With this in hand, a computer can be convinced&lt;sup id=&quot;fnref:implementation2D&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:implementation2D&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
to find the atoms for you, drawing larger dots for better hotspots.
Try it for several values of \(n\); I suggest 5, 7, 8, 6, 2, 12, and 11.&lt;/p&gt;

&lt;div class=&quot;demo-link&quot;&gt;&lt;a href=&quot;/quasi/2d.html&quot;&gt;&lt;img alt=&quot;Thumbnail&quot; src=&quot;/quasi/thumb-2d.png&quot; itemprop=&quot;image&quot; /&gt;&lt;span class=&quot;demo-text&quot;&gt;Demo&lt;br /&gt;2-D quasicrystals&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;

&lt;dl&gt;
  &lt;dt&gt;Remark&lt;/dt&gt;
  &lt;dd&gt;An alternative method is to slice fundamental domains (\(n\)-cubes)
with the 2-plane, which yields pictures like the Penrose tiling below.
Jason Davies has &lt;a href=&quot;http://www.jasondavies.com/tuebingen/&quot;&gt;an applet you can play with&lt;/a&gt;,
based on &lt;a href=&quot;http://www.gregegan.net/APPLETS/31/31.html&quot;&gt;an older one&lt;/a&gt; by Greg Egan.&lt;/dd&gt;
&lt;/dl&gt;

&lt;figure&gt;
&lt;img alt=&quot;A Penrose Tiling&quot; title=&quot;A Penrose Tiling&quot; src=&quot;/w/up/penrose.png&quot; /&gt;&lt;figcaption&gt;A Penrose Tiling&lt;br /&gt;by Inductiveload &lt;a href=&quot;http://commons.wikimedia.org/wiki/File:Penrose_Tiling_(Rhombi).svg&quot;&gt;on Wikimedia Commons&lt;/a&gt; (PD)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;self-similarity&quot;&gt;Self-similarity&lt;/h2&gt;

&lt;p&gt;At this point, we could go home&amp;mdash;we have a description of quasicrystals
from which we can produce both interactive computer renderings and
theorems (like quasicrystals not actually having translational symmetry,
due to \(V\) containing no integer points besides 0).&lt;/p&gt;

&lt;p&gt;Of course, there is more&amp;mdash;the &amp;ldquo;quasi&amp;rdquo;-ness of quasicrystals allows a
sort of self-similarity that honest crystals can&amp;rsquo;t have. To see it in
action, go back to &lt;a href=&quot;/quasi/2d.html&quot;&gt;that atoms demo&lt;/a&gt; and try zooming in or out
for a while.&lt;/p&gt;

&lt;p&gt;To explain this self-similarity&amp;mdash;the apparent
indistinguishability of different zoom levels&amp;mdash;we will need
a bit of number theory.&lt;/p&gt;

&lt;h3 id=&quot;a-number-theoretic-model-of-quasicrystals&quot;&gt;A number-theoretic model of quasicrystals&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;Theorem (crystallographic restriction in arbitrary dimensions)&lt;/dt&gt;
  &lt;dd&gt;\(\operatorname{GL}_m \mathbb{Z} \) contains a matrix \(A\) which
has \(\zeta_n = e^{2\pi i/n}\) as an eigenvalue
(so it rotates some 2-plane by \(\frac{2 \pi}{n}\))
if and only if \(m \geq \varphi(n)\), where \(\varphi\) is
&lt;a href=&quot;http://en.wikipedia.org/wiki/Euler%27s_totient_function&quot;&gt;Euler&amp;rsquo;s totient function&lt;/a&gt;.&lt;/dd&gt;
&lt;/dl&gt;

&lt;dl&gt;
  &lt;dt&gt;Proof&lt;/dt&gt;
  &lt;dd&gt;The Galois conjugates of \(\zeta_n\) must also be eigenvalues
of \(A\).

    &lt;ul&gt;
      &lt;li&gt;Since \(\zeta_n^n = 1\), they&amp;rsquo;re \(n\)th roots of 1.&lt;/li&gt;
      &lt;li&gt;Since \(\zeta_n\) generates all \(n\)th roots of 1,
they&amp;rsquo;re primitive&amp;mdash;i.e. \(\zeta_n^k\) where
\(k\) and \(n\) are coprime.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;The number of such \(k\) is \(\varphi(n)\). To prove that
\(\varphi(n)\) works, observe that
\[ \mathbb{Z}[\zeta_n] \hookrightarrow \mathbb{Q}(\zeta_n) \cong_{\mathbb{Q}\text{-vect}} \mathbb{Q}^{\varphi(n)} \subset \mathbb{R}^{\varphi(n)} \]
as a discrete subgroup, since the &lt;a href=&quot;http://en.wikipedia.org/wiki/Field_norm&quot;&gt;field norms&lt;/a&gt;
of the leftmost terms are in \(\mathbb{Z}\).&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;dl&gt;
  &lt;dt&gt;Remark&lt;/dt&gt;
  &lt;dd&gt;If \(p\) and \(q\) are large enough primes,
you can produce an integer matrix \(A\) of order \(pq\)
and size \(\varphi(p) + \varphi(q) &amp;lt; \varphi(pq)\),
but it won&amp;rsquo;t rotate any 2-plane by \(\frac{2\pi}{pq}\).&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3 id=&quot;a-mathematical-description-of-zooming&quot;&gt;A mathematical description of zooming&lt;/h3&gt;

&lt;p&gt;Here&amp;rsquo;s how we implement&lt;sup id=&quot;fnref:zoomImplementation&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:zoomImplementation&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; zooming:
scale the 2-plane \(V\) by some factor
and the unseen \(m-2\) dimensions by some other factor to
preserve \(m\)-dimensional volume. That way the total visual density
of dots remains about the same.
Here&amp;rsquo;s how we interpret zooming and self-similarity:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zooming acts by scalars on \(V\) and the other irreducible
sub-representations of
\(\langle A \rangle \curvearrowright \mathbb{R}^{\varphi(n)}\),
so zooming is a 1-parameter subgroup \(\gamma\) in
\(\operatorname{SAut}_A \mathbb{R}^{\varphi(n)} \)
(volume preserving automorphisms).&lt;/li&gt;
  &lt;li&gt;Visually, transforming by anything in
\(\operatorname{Aut} \mathbb{Z}[\zeta_n]\)
isn&amp;rsquo;t detectable.&lt;/li&gt;
  &lt;li&gt;Self-similarity means that the image of \(\gamma\) in
\(\operatorname{SAut}_A \mathbb{R}^{\varphi(n)} / \operatorname{Aut} \mathbb{Z}[\zeta_n]\) accumulates on itself (or is periodic).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The existence of self-similarity rests on one key fact
from number theory.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Theorem (Dirichlet&amp;rsquo;s Unit Theorem)&lt;/dt&gt;
  &lt;dd&gt;Suppose a number field has \(r\) embeddings in \(\mathbb{R}\) and
\(c\) embeddings in \(\mathbb{C}\). Then its group of units has rank
\[ r + \frac{c}{2} - 1 . \]&lt;/dd&gt;
  &lt;dt&gt;Corollary&lt;/dt&gt;
  &lt;dd&gt;\(\operatorname{SAut}_A \mathbb{R}^{\varphi(n)} / \operatorname{Aut} \mathbb{Z}[\zeta_n]\) is compact.&lt;/dd&gt;
  &lt;dt&gt;Proof&lt;/dt&gt;
  &lt;dd&gt;Since automorphisms act by scalars on all irreducible subrepresentations,

    &lt;p&gt;\[\begin{align*}
\operatorname{Aut}_A \mathbb{R}^{\varphi(n)} &amp;amp;\cong (\mathbb{C}^\times)^{\frac{\varphi(n)}{2}} \cong (\mathbb{R} \times S^1)^{\frac{\varphi(n)}{2}} \\ 
\operatorname{SAut}_A \mathbb{R}^{\varphi(n)} &amp;amp;\cong \mathbb{R}^{\frac{\varphi(n)}{2} - 1} \times (S^1)^{\frac{\varphi(n)}{2}} .
\end{align*}\]&lt;/p&gt;

    &lt;p&gt;Since
&lt;a href=&quot;http://mathoverflow.net/questions/17289/&quot;&gt;\(\mathbb{Z}[\zeta_n] = \mathcal{O}_{\mathbb{Q}(\zeta_n)}\)&lt;/a&gt;,
Dirichlet&amp;rsquo;s Unit Theorem implies that
\(\operatorname{Aut} \mathbb{Z}[\zeta_n]\) contains a copy of
\(\mathbb{Z}^{\frac{\varphi(n)}{2} - 1}\).
Then \(\operatorname{Aut} \mathbb{Z}[\zeta_n]\),
being discrete (it&amp;rsquo;s conjugate to a subgroup of
\(\operatorname{SL}(\varphi(n), \mathbb{Z})\)),
is cocompact.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Self-similarity now follows, having been reduced to the statement that
a 1-parameter subgroup of a torus is recurrent.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Remark&lt;/dt&gt;
  &lt;dd&gt;The image of \(\gamma\) is periodic when (and only when)
\(\varphi(n) = 2\)&amp;mdash;so when \(n\) is 5, 8, 10, or 12.
This makes the self-similarity exact&amp;mdash;i.e. different zoom levels
can look identical (not just suspiciously similar)&amp;mdash;and allows one
to build games like Richard Schwartz&amp;rsquo;s &lt;a href=&quot;http://www.math.brown.edu/~res/Java/App12/test1.html&quot;&gt;Lucy and Lily&lt;/a&gt;
based on facts like
    \[ (2 + \sqrt{5})(2 - \sqrt{5}) = -1. \]&lt;/dd&gt;
  &lt;dt&gt;Remark&lt;/dt&gt;
  &lt;dd&gt;Michael Rule&amp;rsquo;s
&lt;a href=&quot;http://wealoneonearth.blogspot.com/search/label/quasicrystal&quot;&gt;collection of quasicrystals graphics&lt;/a&gt;
includes an &lt;a href=&quot;http://wealoneonearth.blogspot.com/2011/11/visual-analogue-of-shepard-tone.html&quot;&gt;alternative description of zooming&lt;/a&gt;
that sidesteps the number theory, instead using
&lt;a href=&quot;http://en.wikipedia.org/wiki/Shepard_tone&quot;&gt;Shepard Tones&lt;/a&gt; to produce self-similarity.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;3-d-quasicrystals&quot;&gt;3-D quasicrystals&lt;/h2&gt;

&lt;h3 id=&quot;the-n-dimensional-viewpoint&quot;&gt;The n-dimensional viewpoint&lt;/h3&gt;

&lt;p&gt;A quasicrystal with irreducible symmetry \(G\) is
an irreducible-over-\(\mathbb{R}\) subrepresentation \(V\) of
an irreducible-over-\(\mathbb{Z}\) representation
\(G \hookrightarrow \operatorname{SL}(m,\mathbb{Z})\).
The atoms are points of \(\mathbb{Z}^m\) near \(V\),
and the Galois conjugates of \(V\)
(the other subrepresentations over \(\mathbb{R}\))
allow the possibility for self-similarity.&lt;/p&gt;

&lt;h3 id=&quot;the-search-for-3-d-quasicrystals&quot;&gt;The search for 3-D quasicrystals&lt;/h3&gt;

&lt;p&gt;To look for 3-dimensional quasicrystals, one first finds a list of the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Point_groups_in_three_dimensions#The_seven_remaining_point_groups&quot;&gt;seven irreducible finite subgroups of \(\operatorname{SL}(3,\mathbb{R})\)&lt;/a&gt;.
Most of these preserve an ordinary 3-D lattice&amp;mdash;i.e. the representation
can be defined over \(\mathbb{Z}\). The two exceptions are
the two icosahedral groups&amp;mdash;the &lt;a href=&quot;http://en.wikipedia.org/wiki/Alternating_group&quot;&gt;alternating group&lt;/a&gt;
\(A_5\) and the product \(A_5 \times \{\pm 1\}\)&amp;mdash;so up to
finite index subgroups, &lt;a href=&quot;http://en.wikipedia.org/wiki/Tigger&quot;&gt;there&amp;rsquo;s only one&lt;/a&gt;
irreducible 3-D quasicrystal, which you can explore in the following demo.&lt;/p&gt;

&lt;div class=&quot;demo-link&quot;&gt;&lt;a href=&quot;/quasi/3d.html&quot;&gt;&lt;img alt=&quot;Thumbnail&quot; src=&quot;/quasi/thumb-3d.png&quot; /&gt;&lt;span class=&quot;demo-text&quot;&gt;Demo&lt;br /&gt;3-D quasicrystals&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;The standard representation of \(A_5\) has one Galois conjugate,
which can be found in a &lt;a href=&quot;http://groupprops.subwiki.org/wiki/Linear_representation_theory_of_alternating_group:A5&quot;&gt;list of representations of \(A_5\)&lt;/a&gt;.
The two representations can be described explicitly as follows:
in the standard representation,
\(A_5\) acts by rotation on the icosahedron with vertices
\(\pm(\sqrt{5}, 0)\) and \(\pm(1, 2\zeta_5^k)\)
in \(\mathbb{R} \times \mathbb{C}\).
To obtain the other representation,
merely conjugate the action on the set of vertices by
the permutation induced by \(\zeta_5 \mapsto \zeta_5^2\).&lt;/p&gt;

&lt;p&gt;Oh, and&amp;mdash;yes, they&amp;rsquo;re real.&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;A Ho-Mg-Zn quasicrystal over a millimeter grid&quot; title=&quot;A Ho-Mg-Zn quasicrystal over a millimeter grid&quot; src=&quot;/w/up/homgzn-quasi.jpg&quot; /&gt;&lt;figcaption&gt;A Ho-Mg-Zn quasicrystal over a millimeter grid&lt;br /&gt;by AMES Lab., US DoE &lt;a href=&quot;http://commons.wikimedia.org/wiki/File:Ho-Mg-ZnQuasicrystal.jpg&quot;&gt;via Wikimedia Commons&lt;/a&gt; (PD)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:phaseRecovery&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The photo loses phase information, the recovery of which
is &lt;a href=&quot;http://en.wikipedia.org/wiki/Phase_problem&quot;&gt;a nontrivial problem&lt;/a&gt;.&amp;nbsp;&lt;a href=&quot;#fnref:phaseRecovery&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:implementation2D&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;For efficiency reasons, the demo actually uses
the number-theoretic model from the section after.&amp;nbsp;&lt;a href=&quot;#fnref:implementation2D&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:zoomImplementation&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Self-similarity is what makes zooming possible
(i.e. not unbearably slow) in the atoms demo&amp;mdash;the atom finder can
get away with exploring a 2-dimensional slice instead of the
entire \(m\)-dimensional space.&amp;nbsp;&lt;a href=&quot;#fnref:zoomImplementation&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 30 Oct 2015 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2015/quasi/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2015/quasi/</guid>
        
        <category>math</category>
        
        
      </item>
    
      <item>
        <title>Sol geometry and the tangent bundle of a hyperbola</title>
        <description>&lt;p itemprop=&quot;description&quot;&gt;If you try to make rigid motions in some dimension act
as transformations of a lower-dimensional space, you might
hope that it respects some structure in the lower-dimensional space.
Unfortunately this is guaranteed for neither distances nor angles.
Here are some pictures&amp;mdash;one of which is interactive (!)&amp;mdash;for a
particularly pretty example using Thurston&amp;rsquo;s Sol geometry.&lt;/p&gt;

&lt;p class=&quot;tex-macros&quot;&gt;\(
\newcommand{\R}{\mathbb{R}}
\newcommand{\H}{\mathbb{H}}
\newcommand{\SO}{\operatorname{SO}}
\newcommand{\Sol}{\operatorname{Sol}}
\)&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;dl&gt;
  &lt;dt&gt;Definition&lt;/dt&gt;
  &lt;dd&gt;\(\Sol^3\) is the Lie group
\(\R^2 \rtimes \SO(1,1)^0\).&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Visualize \(\Sol^3\) as a line&amp;rsquo;s worth of copies of \(\R^2\),
where moving up or down in the stack stretches them in one direction and
shrinks them by the same factor in the other.&lt;/p&gt;

&lt;figure&gt;
&lt;canvas id=&quot;fig_sol3&quot; width=&quot;256&quot; height=&quot;256&quot; style=&quot;border-width: 1px; border-style: solid;&quot;&gt;
&lt;img itemprop=&quot;image&quot; src=&quot;/w/up/sol3-thumb.png&quot; alt=&quot;Sol3 is a stack of planes.&quot; /&gt;
&lt;/canvas&gt;
&lt;figcaption&gt;\(\Sol^3\) is a stack of planes. (Interactive)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;/w/up/sol3.js&quot; data-canvas=&quot;#fig_sol3&quot;&gt;&lt;/script&gt;

&lt;p&gt;We are interested in the action of \(\Sol^3\) on the tangent bundle
\(T\H^1\) of one branch of a hyperbola.&lt;/p&gt;

&lt;h2 id=&quot;description-of-the-action&quot;&gt;Description of the action&lt;/h2&gt;

&lt;p&gt;Let \(\mathcal{F}\) be the 1-D foliation spanned by
\((\cosh z, \sinh z, 0)\) at \((x,y,z)\).
Under the metric \(dx^2 - dy^2\) on a plane \(\{(*,*,z)\}\),
the line tangent to \(x^2 - y^2 = 1\) at \((\cosh z, \sinh z, 0)\)
is orthogonal to \(\mathcal{F}\). This identifies \(\Sol^3/\mathcal{F}\)
with the tangent bundle \(T\H^1\) of one branch of \(x^2 - y^2 = 1\).&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;A tangent line to a hyperbola&quot; title=&quot;A tangent line to a hyperbola&quot; src=&quot;/w/up/h1-tangent.svg&quot; class=&quot;grayscale-invertible&quot; /&gt;&lt;figcaption&gt;A tangent line to a hyperbola&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;Since \(\mathcal{F}\) is left-invariant (being spanned by a left-invariant
vector field), the left action of \(\Sol^3\) on itself descends to
\(T\H^1\).
Letting \((p,q)\) denote a tangent velocity of \(p\) at \(q \in \H^1\),
you can check that this action is given by
\[
\begin{align*}
(0,0,z)(p,q) &amp;amp;= (p,q+z) \\ 
(x,y,0)(p,q) &amp;amp;= (p+y \cosh q - x \sinh q, q) .
\end{align*}
\]&lt;/p&gt;

&lt;figure&gt;
&lt;img alt=&quot;A diffeomorphism and the image of the q-axis&quot; title=&quot;A diffeomorphism and the image of the q-axis&quot; src=&quot;/w/up/sinh-pq.svg&quot; class=&quot;grayscale-invertible&quot; /&gt;&lt;figcaption&gt;A diffeomorphism and the image of the q-axis&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;no-preservation-of-distances-or-angles&quot;&gt;No preservation of distances or angles&lt;/h2&gt;

&lt;p&gt;Were we hoping to preserve either in \(T\H^1\),
we&amp;rsquo;d be out of luck&amp;mdash;the stabilizer of \((0,0)\) consists of maps
\[
(p,q) \overset{(x,0,0)}{\mapsto} (p - x \sinh q, q) ,
\]
whose action on the tangent space \(T_{(0,0)}(T\H^1)\) is by matrices
\[ \begin{pmatrix} 1 &amp;amp; * \\ &amp;amp; 1 \end{pmatrix}. \]&lt;/p&gt;

&lt;h2 id=&quot;diffy-queues&quot;&gt;Diffy queues&lt;/h2&gt;

&lt;p&gt;You can check using the formula that
\(\Sol^3\) acts faithfully on \(T\H^1\).
In fact, here&amp;rsquo;s a nice description of
\(\Sol^3\) as its image in \(\operatorname{Diff} T\H^1\).&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Proposition&lt;/dt&gt;
  &lt;dd&gt;The image of \(\Sol^3\) in \(\operatorname{Diff} T\H^1\)
consists of the diffeomorphisms \(f = (f_p, f_q)\) that satisfy
\[
\begin{align*}
\frac{\partial f_p}{\partial p} &amp;amp;= 1 &amp;amp;
\frac{\partial^2 f_p}{\partial q^2} &amp;amp;= f_p \\ 
\frac{\partial f_q}{\partial p} &amp;amp;= 0 &amp;amp;
\frac{\partial f_q}{\partial q} &amp;amp;= 1 .
\end{align*}
\]&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;recovering-the-group&quot;&gt;Recovering the group&lt;/h2&gt;

&lt;p&gt;To put it another way, the image consists of those diffeomorphisms
expressible as \(P \circ Q_z\) where&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;\(Q_z\) is translation by \((0,z)\), and&lt;/li&gt;
  &lt;li&gt;\(P\) adds to \(p\) some linear combination of
\(\cosh q\) and \(\sinh q\) (or of \(e^q\) and \(e^{-q}\)).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To see that this is \(\Sol^3\),
parametrize the space \(V\) of images of the \(q\)-axis as
\[
V = \{ \text{graph of } (q \mapsto xe^q + ye^{-q}) \mid x,y \in \R \} .
\]
Then \(Q_z\), sending \(q\) to \(q+z\), acts on \(V\) by
\( Q_z (x,y) = (xe^z, ye^{-z}) \),
so
\[\Sol^3 = V \rtimes \{Q_z \mid z \in \R\} . \]&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Remark&lt;/dt&gt;
  &lt;dd&gt;This is an &lt;a href=&quot;http://mathworld.wolfram.com/SolGeometry.html&quot;&gt;alternative parametrization&lt;/a&gt; of \(\Sol^3\)
under which the action on \(T\H^1\) becomes
\[ (x,y,z)(p,q) = (p + ye^{q+z} - xe^{-q-z}, q+z) . \]&lt;/dd&gt;
&lt;/dl&gt;

</description>
        <pubDate>Tue, 21 Jul 2015 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2015/solgeometry/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2015/solgeometry/</guid>
        
        <category>math</category>
        
        
      </item>
    
      <item>
        <title>window.requestAnimationFrame troubles</title>
        <description>&lt;p&gt;Some old posts about window.requestAnimationFrame (like &lt;a href=&quot;http://www.nczonline.net/blog/2011/05/03/better-javascript-animations-with-requestanimationframe/&quot;&gt;this one&lt;/a&gt;) depend on the callback taking, as an argument, the time the next frame will be displayed. Unforunately, as some have noticed, they&amp;rsquo;re kind of wrong: &lt;a href=&quot;http://impactjs.com/forums/impact-engine/misuse-of-requestanimationframe#post26834&quot;&gt;it&amp;rsquo;s the time the frame started processing&lt;/a&gt;. Here&amp;rsquo;s what I gathered when I tried to figure out why&amp;hellip;&lt;/p&gt;

&lt;p&gt;The current state of affairs seems to be able to differ from what MDN and the spec say only &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp?annotate=blame&amp;amp;rev=173704#L102&quot;&gt;in Webkit on Cocoa&lt;/a&gt; (OS X and iOS), but &lt;a href=&quot;http://pteromys.github.io/testcases/raftime.html&quot;&gt;testing&lt;/a&gt; on an iPhone and a Macbook gives results in line with the spec.&lt;/p&gt;

&lt;p&gt;By May 2011, &lt;a href=&quot;http://www.w3.org/2010/webperf/track/issues/2&quot;&gt;it was noticed that the spec didn&amp;rsquo;t actually define the callback&amp;rsquo;s argument unambiguously&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In November, &lt;a href=&quot;http://lists.w3.org/Archives/Public/public-web-perf/2011Nov/0002.html&quot;&gt;discussion arrived at the following consensus&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The working group feels the time parameter should be the time of the next frame. As developers will typically want to construct the next frame to be painted, this seems like the intuitive option. James or Cameron should also follow up with CSS animations and other animation specs and ensure this design is consistent with any similar concepts they may have.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In May, the relevant section of the spec &lt;a href=&quot;https://dvcs.w3.org/hg/webperf/raw-file/4843fb42912f/specs/RequestAnimationFrame/Overview.html#processingmodel&quot;&gt;was updated&lt;/a&gt; to match what &lt;a href=&quot;http://lists.w3.org/Archives/Public/public-web-perf/2012May/0061.html&quot;&gt;the actual behavior had been all along&lt;/a&gt; in IE, Chrome, and Firefox.&lt;/p&gt;

&lt;p&gt;(In March, plans to make the time parameter a DOMHighResTimestamp had moved forward, but this didn&amp;rsquo;t actually have any effect on the semantic meaning of the callback parameter.)&lt;/p&gt;

&lt;p&gt;I have to wonder whether &lt;a href=&quot;http://lists.w3.org/Archives/Public/public-web-perf/2012May/0053.html&quot;&gt;Paul Irish&amp;rsquo;s message&lt;/a&gt; approving local high-resolution timestamps was also intended to approve of this change, from &amp;ldquo;next frame display time&amp;rdquo; to &amp;ldquo;started processing&amp;rdquo;, given some seemingly-mostly-ignored comments from outside developers on the mailing list (&lt;a href=&quot;http://lists.w3.org/Archives/Public/public-web-perf/2012May/0056.html&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;http://lists.w3.org/Archives/Public/public-web-perf/2011Jul/0074.html&quot;&gt;2&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The last word on the issue was that the predicted time of refresh would likely be &lt;a href=&quot;http://lists.w3.org/Archives/Public/public-web-perf/2012May/0067.html&quot;&gt;passed as a second parameter&lt;/a&gt;. Alas, this could conflict with &lt;a href=&quot;http://www.w3.org/2010/webperf/track/issues/4&quot;&gt;intentions to depend on element visibility&lt;/a&gt;; though &lt;a href=&quot;http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/&quot;&gt;this post of Paul Irish&lt;/a&gt; suggests that intention&amp;rsquo;s gone.&lt;/p&gt;

&lt;p&gt;Side note: The MDN docs were only &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame$compare?to=516121&amp;amp;from=508625&quot;&gt;updated to the spec this January&lt;/a&gt;, even though info on DOMHighResTimestamp &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame$compare?to=460315&amp;amp;from=452757&quot;&gt;was there in August 2013&lt;/a&gt; when the relevant change landed.&lt;/p&gt;

</description>
        <pubDate>Thu, 09 Oct 2014 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2014/raf/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2014/raf/</guid>
        
        <category>history</category>
        
        
      </item>
    
      <item>
        <title>Highlights of Simon Tatham's puzzle collection</title>
        <description>&lt;p&gt;I recently discovered &lt;a href=&quot;http://www.chiark.greenend.org.uk/~sgtatham/puzzles/devel/writing.html&quot;&gt;Simon Tatham&amp;rsquo;s remarks&lt;/a&gt; on writing friendly (i.e. guaranteed solvable) puzzle games. Of note:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;a variant of minesweeper that never requires you to guess&lt;/li&gt;
  &lt;li&gt;a pile of proofs in &lt;a href=&quot;http://svn.tartarus.org/sgt/puzzles/net.c?view=markup&quot;&gt;net.c&lt;/a&gt;, along with tactics to generate uniquely solvable boards for a game you might know as KNetWalk.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://svn.tartarus.org/sgt/puzzles/untangle.c?view=markup&quot;&gt;untangle.c&lt;/a&gt;, a reimplementation of &lt;a href=&quot;http://en.wikipedia.org/wiki/Planarity&quot;&gt;Planarity&lt;/a&gt; with a different graph generation method (see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static char * new_game_desc&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Thu, 05 Jun 2014 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2014/puzzles/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2014/puzzles/</guid>
        
        <category>math</category>
        
        
      </item>
    
      <item>
        <title>Glue records for Melon Island fixed</title>
        <description>&lt;p&gt;Last night I noticed that my website&amp;rsquo;s had incorrect glue records at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.gtld-servers.net&lt;/code&gt; since probably mid-2012&amp;mdash;which explains why a number of ISPs weren&amp;rsquo;t resolving it at all!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://neuralfibre.com/paul/it/dns-ns-records-are-not-glue-records-or-how-to-break-your-dns-delegation&quot;&gt;Paul Young explains&lt;/a&gt; what this means, and &lt;a href=&quot;http://serverfault.com/questions/210317/#answer-210403&quot;&gt;SmallClanger remarks in this ServerFault answer&lt;/a&gt; that it isn&amp;rsquo;t supposed to happen with modern software. The issue was probed using &lt;a href=&quot;http://dns.squish.net/&quot;&gt;Squish&lt;/a&gt; and dig; and fixed by changing the nameservers listed at the registrar, forcing the glue records to be rewritten. Correctness was checked afterwards using &lt;a href=&quot;https://www.whatsmydns.net/&quot;&gt;whatsmydns.net&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Wed, 26 Feb 2014 00:00:00 +0000</pubDate>
        <link>http://pteromys.melonisland.net/w/2014/glue/</link>
        <guid isPermaLink="true">http://pteromys.melonisland.net/w/2014/glue/</guid>
        
        
      </item>
    
  </channel>
</rss>
