<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Nick Craig-Wood's articles on Nick Craig-Wood's home page</title><link>https://ncw.github.io/www/articles/</link><description>Nick Craig-Wood's article</description><language>en-US</language><copyright>Copyright (c) 1994-2026, Nick Craig-Wood; all rights reserved.</copyright><atom:link href="https://ncw.github.io/www/articles/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Sat, 11 Feb 2023 00:00:00 +0000</lastBuildDate><item><title>Infinity mirror with Raspberry Pi Pico, Neopixels and Micropython</title><link>https://ncw.github.io/www/articles/infinity-mirror/</link><pubDate>Sat, 11 Feb 2023 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/infinity-mirror/</guid><description>&lt;h1 id="infinity-mirror-with-raspberry-pi-pico-neopixels-and-micropython"&gt;Infinity mirror with Raspberry Pi Pico, Neopixels and Micropython&lt;/h1&gt;
&lt;p&gt;Here is an account of how I renovated our old infinity mirror to this:&lt;/p&gt;
&lt;p&gt;&lt;img src="mirror.gif" alt="Animated GIF of mirror"&gt;&lt;/p&gt;
&lt;p&gt;From this:&lt;/p&gt;
&lt;p&gt;&lt;img src="before.jpg" alt="Mirror before"&gt;&lt;/p&gt;
&lt;p&gt;This isn't a recipe on how to do this yourself (though you could
certainly use it like that), its an account of exactly what I did,
including all the bits where I wasn't sure where I was going in the
hope it will help less experienced constructors with the thought
process.&lt;/p&gt;
&lt;h2 id="the-mirror"&gt;The mirror&lt;/h2&gt;
&lt;p&gt;A long time ago my wife and I were looking in a lighting shop and we
came across the infinity mirror. I was immediately captivated by it
and we had it installed in our bathroom when we had it renovated.&lt;/p&gt;
&lt;p&gt;Fast forward more than a decade and the lights in the infinity mirror
had stopped working. I had never taken it apart to see how to fix it
which I really should have done but you know how you get used to
things not working...&lt;/p&gt;
&lt;p&gt;Just before Christmas 2022 I decided I would like to have a project to
work on over the holiday period, so after a very brief bit of
research I ordered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;40 plated through hole neopixel LEDs&lt;/li&gt;
&lt;li&gt;2 raspberry pi pico W microcontrollers&lt;/li&gt;
&lt;li&gt;5V 2A PSU&lt;/li&gt;
&lt;li&gt;40 x 330uF capacitors&lt;/li&gt;
&lt;li&gt;40 x 330Ohm resistors&lt;/li&gt;
&lt;li&gt;Some more wire since I had run out&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I chose the plated through LED style neopixels because I knew they'd
be visible in the mirror and I wanted them to look nicer than the
neopixel strips. I knew I needed 34 LEDs but I ordered some extra for
testing. I ended up breaking a couple of them so just as well.&lt;/p&gt;
&lt;p&gt;I chose the pi pico because I'd done a project with that before with
C++ but I thought it would be fun to try micropython (which I hadn't
tried before).&lt;/p&gt;
&lt;p&gt;The resistors and caps I chose after a bit of looking at the
datasheet. Spoiler - I didn't need these in the end and I did need
some decoupling caps instead - see later.&lt;/p&gt;
&lt;p&gt;I made that order in the full knowledge that it wouldn't be everything
I needed and that there may be stuff in there that I didn't need. When
getting going on a project its much more important for me to make a
start even if it is in the wrong direction than to wait until I've
planned everything out to the last degree.&lt;/p&gt;
&lt;p&gt;Later I ended up ordering:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;40 x 10nF ceramic capacitors&lt;/li&gt;
&lt;li&gt;50 x bezel mounts for the 5mm LEDs&lt;/li&gt;
&lt;li&gt;5 x 100k pots with nice knobs&lt;/li&gt;
&lt;li&gt;5 x switches&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="neopixels"&gt;Neopixels&lt;/h3&gt;
&lt;p&gt;Once the stuff arrived I took some photos to see how the neopixels
worked inside.&lt;/p&gt;
&lt;p&gt;&lt;img src="neopixel-from-top.jpg" alt="crop of neopixel from top"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="neopixel-from-side.jpg" alt="crop of neopixel from side"&gt;&lt;/p&gt;
&lt;p&gt;You can see the 3 LED chips and also the controller chip all connected
together with very fine wire in the LED encapsulation.&lt;/p&gt;
&lt;p&gt;Neopixels have 4 connections, &lt;code&gt;Volts&lt;/code&gt;, &lt;code&gt;Ground&lt;/code&gt;, &lt;code&gt;Data In&lt;/code&gt; and &lt;code&gt;Data Out&lt;/code&gt;. You chain them up &lt;code&gt;Data In&lt;/code&gt; to &lt;code&gt;Data Out&lt;/code&gt; and you connect the
first &lt;code&gt;Data In&lt;/code&gt; to your microcontroller (in this case a Raspberry Pi
Pico). The microcontroller generates a serial data stream with 24 bit
color for each neopixel. The first neopixel uses the first block of
pixel data to color itself and passes the rest of the stream on. This
means you can chain hundreds of them together with only one pin on
your microcontroller and address each one individually.&lt;/p&gt;
&lt;h2 id="neopixels-and-micropython"&gt;Neopixels and micropython&lt;/h2&gt;
&lt;p&gt;The first thing I wanted to do was to make a neopixel work from
micropython to give me some confidence that the project would work.&lt;/p&gt;
&lt;p&gt;I made a plan like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install micropython on the pi pico and make it work&lt;/li&gt;
&lt;li&gt;Breadboard a single neopixel to see if that works&lt;/li&gt;
&lt;li&gt;Breadboard a chain of neopixels to see if they work&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I fully expected these steps to be very hard - bringing up new
hardware is always troublesome.&lt;/p&gt;
&lt;h3 id="installing-micropython"&gt;Installing micropython&lt;/h3&gt;
&lt;p&gt;Installing micropython turned out to be very easy. I installed the
micropython firmware from here&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.raspberrypi.com/documentation/microcontrollers/micropython.html"&gt;https://www.raspberrypi.com/documentation/microcontrollers/micropython.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Using Pico W version &lt;code&gt;rp2-pico-w-20230116-unstable-v1.19.1-803-g1583c1f67.uf2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I then needed to work out how to communicate with micropython. I tried
&lt;code&gt;thonny&lt;/code&gt; but I don't really like graphical clicky GUIs and eventually
I found that Ubuntu packaged &lt;code&gt;rshell&lt;/code&gt; which worked and let me use a
REPL on the board and transfer files into the flash.&lt;/p&gt;
&lt;p&gt;This was so easy compared to microcontroller development I've done in
the past - well done Raspberry Pi and Micropython.&lt;/p&gt;
&lt;p&gt;Having a REPL on the board meant I could do little experiments to see
if bits of hardware were working just by typing python snippets.&lt;/p&gt;
&lt;h3 id="first-light"&gt;First light&lt;/h3&gt;
&lt;p&gt;I soldered on 7 pins to the pico (just enough for power, IO and to
stop it wobbling) then I plugged it into a breadboard with a single
neopixel.&lt;/p&gt;
&lt;p&gt;&lt;img src="single-neopixel.jpg" alt="single neopixel breadboard"&gt;&lt;/p&gt;
&lt;p&gt;It took me a little while to discover that there is a built in
neopixel library in the pico micropython. I found an external library
first but decided to use the built in library after evaluating it.&lt;/p&gt;
&lt;p&gt;I could then use the REPL from &lt;code&gt;rshell&lt;/code&gt; to write code and try to make
neopixel work.&lt;/p&gt;
&lt;p&gt;This should set the LED to a pink color:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; neopixel &lt;span style="color:#f92672"&gt;import&lt;/span&gt; NeoPixel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; machine
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pin &lt;span style="color:#f92672"&gt;=&lt;/span&gt; machine&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Pin(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixels &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NeoPixel(pin, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixels&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fill((&lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixels&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However it didn't set it to pink at all! Eventually I worked out that
the ordering of RGB seems to be wrong. I looked in the source for the
neopixel python library and saw I could fix it like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NeoPixel&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ORDER &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So a test of the LED became:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; neopixel &lt;span style="color:#f92672"&gt;import&lt;/span&gt; NeoPixel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NeoPixel&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ORDER &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; machine
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pin &lt;span style="color:#f92672"&gt;=&lt;/span&gt; machine&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Pin(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixels &lt;span style="color:#f92672"&gt;=&lt;/span&gt; NeoPixel(pin, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixels&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fill((&lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixels&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It was a relief to get over that hurdle - it seemed then that the
project might work after all.&lt;/p&gt;
&lt;h3 id="fifth-light"&gt;Fifth light&lt;/h3&gt;
&lt;p&gt;I then extended the breadboard with 4 more neopixels for 5 in total
and tried to make that work.&lt;/p&gt;
&lt;p&gt;&lt;img src="five-neopixels.jpg" alt="5 neopixels"&gt;&lt;/p&gt;
&lt;p&gt;I then had fun noodling around with python to try to make some
interesting patterns.&lt;/p&gt;
&lt;video autoplay loop muted playsinline style="max-width:100%; border-radius: 8px;"&gt;
&lt;source src="five-neopixels-lightshow.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;p&gt;Note that the neopixels are extremely bright when on full power so I
did most of this testing with a bit of white paper over the neopixels.
When the neopixels are in the mirror they will shine sideways not
towards the viewer to make interesting internal reflections. This
worked out very well.&lt;/p&gt;
&lt;h3 id="knobs"&gt;Knobs&lt;/h3&gt;
&lt;p&gt;At this point I realised it would be nice if the user had some control
over the display. A brightness knob at minimum would be nice!&lt;/p&gt;
&lt;p&gt;The Pico has 3 ADC pins so I bought some 100k pots with knobs off eBay
and wired them up and soldered them to the pico.&lt;/p&gt;
&lt;video autoplay loop muted playsinline style="max-width:100%; border-radius: 8px;"&gt;
&lt;source src="knobs.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;p&gt;Later I discovered that 100k was too big a value as they are a bit
noisy and can't quite pull up and down to the rails due to the
internal resistance of the pico ADC. I chose the 100k to save a bit of
power but it was a mistake - 10k pots would have been better. I left
them at 100k though and did a bit of work in the software to make sure
they could hit completely off and completely on.&lt;/p&gt;
&lt;p&gt;I also at this point decided to add two buttons for mode up and mode
down but I didn't make them until later.&lt;/p&gt;
&lt;h2 id="mechanical-work"&gt;Mechanical work&lt;/h2&gt;
&lt;p&gt;Now that I had proved the concept of the pico and neopixels it was
time for me to disassemble the mirror. I really should have done this
before I started, but I guess I enjoy the feeling of not knowing what
I'm doing ;-)&lt;/p&gt;
&lt;p&gt;&lt;img src="before.jpg" alt="Mirror before"&gt;&lt;/p&gt;
&lt;p&gt;You can see the mirror has what is essentially a string of Christmas
lights inside. These gave a beautiful creamy light so I hope I don't
destroy that with the LEDs.&lt;/p&gt;
&lt;p&gt;&lt;img src="inner-mirror.jpg" alt="pic of inner of mirror"&gt;&lt;/p&gt;
&lt;p&gt;Each Christmas light came out through a hole about 10mm in diameter
and I had to work out how to fit the LEDs which are 5mm in diameter
into those holes neatly. This is all very visible so it had to look
nice.&lt;/p&gt;
&lt;p&gt;This was probably the hardest part of the project for me. If I had a
3D printer I guess I could have printed something up.&lt;/p&gt;
&lt;p&gt;After a lot of messing about, I eventually bought some panel mounts
for the LEDs. This made them up to 8 mm in diameter. They were not
quite big enough and it took a lot of force to get the LEDs far enough
into the panel mounts. I broke a couple of LEDs doing it!&lt;/p&gt;
&lt;p&gt;Then I cut about 1cm off the end of all the Christmas lights (with a
saw!) so I could re-use the little bit of green plastic tube you see
below and put the panel mount into those which luckily fit perfectly.&lt;/p&gt;
&lt;p&gt;&lt;img src="leds-ready.jpg" alt="LEDs ready for mounting"&gt;&lt;/p&gt;
&lt;p&gt;At last the LEDs were ready to fit into the 10mm holes in the frame.&lt;/p&gt;
&lt;p&gt;&lt;img src="leds-in-frame.jpg" alt="pic of LEDs in the frame"&gt;&lt;/p&gt;
&lt;p&gt;I then soldered the wires to connect up the neopixels. I also soldered
a 10nF decoupling capacitor across the power lines for each one. The
datasheet recommended feeding each one through a resistor with a
reservoir capacitor, but in my tests the 5V PSU I had bought was
plenty capable of dealing with the power surges so I just went for a
decoupling capacitor to minimise noise.&lt;/p&gt;
&lt;p&gt;This was a lot of soldering - it took about 4 hours to make and solder
all the wires. There are 3 wires for each LED that needed making and 4
solder joints, so 204 wire ends to strip and tin and 102 joints to
make with 3 or 4 things being soldered together!&lt;/p&gt;
&lt;p&gt;&lt;img src="soldering.jpg" alt="pic of soldering"&gt;&lt;/p&gt;
&lt;p&gt;With the benefit of 20/20 hindsight and a bit more searching eBay and
Amazon I could have bought a string of Christmas light neopixels which
probably would have done the job with much less soldering.&lt;/p&gt;
&lt;p&gt;I then connected the breadboard and made sure the lights worked.&lt;/p&gt;
&lt;h2 id="software"&gt;Software&lt;/h2&gt;
&lt;p&gt;Now the hardware unknowns were beaten for the moment it was time to
get back to the software.&lt;/p&gt;
&lt;p&gt;You can &lt;a href="https://github.com/ncw/mirror"&gt;download the software from github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One thing I did do which I recommend you always do when working with
embedded stuff is write a simulator.&lt;/p&gt;
&lt;p&gt;&lt;img src="simulator.png" alt="screenshot of simulator"&gt;&lt;/p&gt;
&lt;p&gt;I used pygame for this. This meant I could test and debug the display
modes on my desktop which was a much quicker cycle than testing on the
raspberry pi pico. It's also a nice thing to have - you can download
the code from the github repo and try it yourself even if you don't
have any hardware.&lt;/p&gt;
&lt;p&gt;I went through a few iterations of how exactly to split the code
between the simulator and micropython but in the end passing a
&lt;code&gt;mirror&lt;/code&gt; object to each mode turned out the easiest.&lt;/p&gt;
&lt;p&gt;I experimented with different frame rates and I found that 50 Hz was
too fast - some of the modes were dropping frames so I settled on 25
Hz.&lt;/p&gt;
&lt;p&gt;I also experimented with running the refresh off a timer interrupt in
micropython. This worked for a while and then locked up and I
conjecture I was doing too much on the interrupt. I switched it over
to a timed sleep and it became 100% reliable after that.&lt;/p&gt;
&lt;p&gt;I experimented with lots of different modes and had the idea of using
the board's temperature sensor for a temperature display mode and using
the on board WiFi to pick up the current time for a clock mode. The
clock mode actually works really well - with a few minutes' practice you
can read it just like any analogue clock.&lt;/p&gt;
&lt;h2 id="final-assembly"&gt;Final assembly&lt;/h2&gt;
&lt;p&gt;Now that the software was looking good I went back to the hardware
side for the final assembly.&lt;/p&gt;
&lt;p&gt;I needed to get the pico off the bread board and mounted into the mirror somehow.&lt;/p&gt;
&lt;p&gt;In the end I decided to make a piece of wood which I would velcro
underneath the mirror (there is a small gap so it won't be visible)
and put the pico and knobs there.&lt;/p&gt;
&lt;video autoplay loop muted playsinline style="max-width:100%; border-radius: 8px;"&gt;
&lt;source src="final-construction.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;p&gt;This taxed my meagre carpentry skills. I made a mistake with the
knobs - the bit of wood I chose was too thick to put the nuts on the
knob shafts to hold them in which was a bit of a disaster. However I
decided to epoxy them and the buttons in place which made a nice
result provided I don't ever want to take them off again.&lt;/p&gt;
&lt;p&gt;I fed the power (5V, GND) in to the top of the mirror and out of the
bottom of the mirror comes 3 wires, 5V, GND and the input to the
string of neopixels. The 5V line goes via a diode to VSYS on the pico
so that the pico can be powered via the USB or by the external 5V PSU.
This arrangement is outlined in the datasheet for the pico.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;VBUS is the 5V input from the micro-USB port, which is fed through a
Schottky diode to generate VSYS. The VBUS to VSYS diode (D1) adds
flexibility by allowing power ORing of different supplies into VSYS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and later&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The simplest way to safely add a second power source to Pico is to
feed it into VSYS via another Schottky diode (see Figure 15). This
will 'OR' the two voltages, allowing the higher of either the
external voltage or VBUS to power VSYS, with the diodes preventing
either supply from back-powering the other.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We will run the LEDs directly from an external 5V power supply. Since
the VSYS input range is 1.8V to 5.5V we don't need to worry about a
diode drop, so any silicon diode should be fine.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;So via a diode connect external 5V PSU to VSYS&lt;/li&gt;
&lt;li&gt;Leave VBUS unconnected (since it connects directly to the USB power)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will allow us to connect a computer and not blow up the computer
with the external 5V PSU.&lt;/p&gt;
&lt;p&gt;The neopixel drive is connected to GP0 via a 330Ohm resistor. Why the
resistor? Just in case the pin gets shorted to 5V - that will save the
pico in that case.&lt;/p&gt;
&lt;p&gt;I made connectors for the 3 wires to the pico board so I could take it
off and things are very nearly done.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;That was a lot of fun. The mirror is somewhat mesmerising in the color
cycling modes. It also made the wife happy to have the infinity mirror
working again, so win-win-win :-)&lt;/p&gt;
&lt;video autoplay loop muted playsinline style="max-width:100%; border-radius: 8px;"&gt;
&lt;source src="color-cycling.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;h2 id="thanks"&gt;Thanks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Dougal for helping me with the wire stripping&lt;/li&gt;
&lt;li&gt;Dave Lawrence for writing the Matrix and ChaseRGB modes&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Deadlocks: the dark side of concurrency</title><link>https://ncw.github.io/www/articles/deadlocks-in-go/</link><pubDate>Mon, 25 Oct 2021 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/deadlocks-in-go/</guid><description>&lt;p&gt;This is a transcript of a talk I gave at Gophercon UK on 2021-10-25. You can &lt;a href="https://youtu.be/9j0oQkqzhAE"&gt;watch it on YouTube&lt;/a&gt; (47 minutes) or see the slides and read the words here.&lt;/p&gt;
&lt;p&gt;Go makes it so easy to write concurrent programs that sooner or later you will run into a deadlock. A deadlock is where your program (or part of it) just stops working for mysterious reasons.&lt;/p&gt;
&lt;p&gt;This talk will explain what deadlocks are and why the Go deadlock detector isn't very useful in real world programs.&lt;/p&gt;
&lt;p&gt;Deadlocks can be very difficult to find and fix and this talk will give lots of tips on how to figure out why your program deadlocked and how to fix it and avoid deadlocks in the future.&lt;/p&gt;
&lt;p&gt;You will need an understanding of go routines, locking (sync.Mutex) and channels to get the most out of this talk. No previous deadlock experience required!&lt;/p&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-01.png" alt="Slide: Title - Deadlocks in Go" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Hello and welcome everyone.&lt;/p&gt;
&lt;p&gt;I’m Nick Craig-Wood and I’m going to be talking to you about deadlocks.&lt;/p&gt;
&lt;p&gt;This is an intermediate level talk, so I’m assuming you know what a go routine is and have some idea what a channel and a mutex is.&lt;/p&gt;
&lt;p&gt;I’ve put a link to the &lt;a href="https://github.com/ncw/go-deadlocks-talk"&gt;code samples&lt;/a&gt; up there – you don’t need them as I’ll be putting them on the screen, but you can have them for reference during the talk or later.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-02.png" alt="Slide: Talk overview" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;In this talk we are going to talk about what a deadlock is, how to debug them and how to avoid them in future.&lt;/p&gt;
&lt;p&gt;It will have lots of real world examples culled from dozens of painful examples in the &lt;a href="https://rclone.org"&gt;rclone&lt;/a&gt; codebase!&lt;/p&gt;
&lt;p&gt;I learned about deadlocks the hard way by having to debug lots of them and I’m aiming of for this to be the talk I would have like to listened to when I knew nothing.&lt;/p&gt;
&lt;p&gt;Hopefully everyone, no matter how experienced will pick up a few tips.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-03.png" alt="Slide: About me" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;But first a little bit about me. At the moment I’m mostly doing Open Source coding on &lt;a href="https://rclone.org"&gt;rclone&lt;/a&gt; with a bit of consultancy.&lt;/p&gt;
&lt;p&gt;I’ve been using Go for 9 years since before version 1.0. I got into it when I was a busy CTO and found I was doing nearly 100% people management and strategy with no time for coding. So I decided I’d learn Go in my spare time because it sounded interesting and I needed a programming activity to keep me sane.&lt;/p&gt;
&lt;p&gt;After writing a few small things in Go, I started started the rclone project in 2012 and its been growing ever since, now with 30 thousand stars on GitHub and millions of downloads a month.&lt;/p&gt;
&lt;p&gt;That’s been quite a ride but I’ll save that story for a different talk!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-04.png" alt="Slide: About rclone" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Since all the real world examples in this talk come from rclone I’ll tell you a little bit about it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://rclone.org"&gt;Rclone&lt;/a&gt; is a highly concurrent command line tool to sync your data to and from any cloud storage system. It supports over 40 providers including s3, dropbox, google drive, azure and lots more.&lt;/p&gt;
&lt;p&gt;It tries to do everything it can to maximise your network and disk bandwidth and minimise the chance of data corruption.&lt;/p&gt;
&lt;p&gt;It can also mount your cloud storage system as a network drive using its FUSE filing system.&lt;/p&gt;
&lt;p&gt;To make it run fast rclone is riddled with Go routines, and the inevitable channels and locks which go with them and in turn the inevitable deadlocks.&lt;/p&gt;
&lt;p&gt;Before I started on the rclone journey I knew nothing about deadlocks!&lt;/p&gt;
&lt;h2 id="what-is-a-deadlock"&gt;What is a deadlock?&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-05.png" alt="Slide: What is a deadlock" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;So what is a deadlock?&lt;/p&gt;
&lt;p&gt;Here is Wikipedia’s rather abstract definition of a deadlock – something to do with one process holding something another process needs.&lt;/p&gt;
&lt;p&gt;I prefer to think of them as a catch 22 situation.&lt;/p&gt;
&lt;p&gt;Rather like a newly graduated developer: you need experience to get a job, but you can’t get experience until you get a job.&lt;/p&gt;
&lt;p&gt;In a deadlock the other process has something you want, and you have something the other process wants and you are both prepared to sit there and block forever until the other process gives you what you need.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-06.png" alt="Slide: Deadlock diagram setup" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Let’s go through a deadlock in diagram form.&lt;/p&gt;
&lt;p&gt;Here we have two go routines (the blue circles labelled Process 1 and Process 2) and two locks (the pink squares).&lt;/p&gt;
&lt;p&gt;Each lock could be a sync.Mutex or a Read Write Mutex or maybe even a write to a channel.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-07.png" alt="Slide: Process 1 takes Lock 1" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The first step is Process 1 takes Lock 1. All good so far.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-08.png" alt="Slide: Process 2 takes Lock 2" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Next step is process 2 takes lock 2. Again all good, nothing to see here.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-09.png" alt="Slide: Process 1 blocked on Lock 2" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Now process 1 attempts to takes lock 2. This causes Process 1 to block and wait for lock 2 to be released as lock 2 is already taken by process 2.&lt;/p&gt;
&lt;p&gt;We haven’t reached deadlock yet as everything could be resolved as soon as Process 2 drops Lock 2.&lt;/p&gt;
&lt;p&gt;However it doesn’t do that...&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-10.png" alt="Slide: Deadlock achieved" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Process 2 now tries to take Lock 1.&lt;/p&gt;
&lt;p&gt;This is unsuccessful because Lock 1 is taken by Process 1 so Process 2 blocks waiting for it to be released.&lt;/p&gt;
&lt;p&gt;Now Process 1 &lt;strong&gt;and&lt;/strong&gt; Process 2 are blocked. They will never proceed as each is waiting for the other to release a lock.&lt;/p&gt;
&lt;p&gt;These two processes are now deadlocked.&lt;/p&gt;
&lt;p&gt;This means that some part of your program has stopped working and will &lt;strong&gt;never&lt;/strong&gt; work again.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-11.png" alt="Slide: Deadlock code example" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Let’s see what that might look like in Go with a simple bit of code.&lt;/p&gt;
&lt;p&gt;We have process 1 and process 2 just like in the previous example and they are going to sit there in a loop, taking and releasing lock1 and lock2.&lt;/p&gt;
&lt;p&gt;The only difference between process1 and process2 is that they take and release the locks in a different order.&lt;/p&gt;
&lt;p&gt;This code looks like it should work, but it will deadlock pretty soon.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-12.png" alt="Slide: Deadlock detector output" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is the output once you run the code.&lt;/p&gt;
&lt;p&gt;First thing to notice is that the Go runtime has detected the deadlock giving the nice friendly message “all go routines are asleep – deadlock”.&lt;/p&gt;
&lt;p&gt;The runtime gives a backtrace of all the Go routines that are running which is very useful for working out what went wrong.&lt;/p&gt;
&lt;p&gt;The disadvantage of this is that they can be very long – even this tiny example needed 2 slides to fit it on.&lt;/p&gt;
&lt;p&gt;Go routine 1 is waiting on the select with no cases that we put in to stop the program ending too soon. We can ignore that.&lt;/p&gt;
&lt;p&gt;Goroutine 17 is in state semacquire – its deadlocked calling the sync Mutex implementation.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-13.png" alt="Slide: Backtrace continued" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is the next bit of the output.&lt;/p&gt;
&lt;p&gt;In goroutine 19 you can see a different bit of our code in also calling the sync Mutex implementation. Again it is deadlocked in the semacquire state.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-14.png" alt="Slide: Annotated deadlock code" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;I’ve put arrows at the bits of code that the backtrace indicates the go routines are executing.&lt;/p&gt;
&lt;p&gt;You can see process1 has taken lock1 and is blocked taking lock2, whereas process 2 has taken lock2 and is blocked taking lock1.&lt;/p&gt;
&lt;p&gt;This is a clear deadlock. Whenever you see a trace where a single go routine takes more than one lock, you should be thinking about deadlocks.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-15.png" alt="Slide: Deadlock diagram confirmed" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is exactly what we expected from our initial diagram, process 1 is blocked taking lock 2 and process 2 is blocked taking lock 1.&lt;/p&gt;
&lt;p&gt;It is nice to see theory and practice agreeing!.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-16.png" alt="Slide: Go deadlock detection limits" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;You’ll have noticed that Go can detect deadlocks.&lt;/p&gt;
&lt;p&gt;This is very useful, but unfortunately it very rarely detects deadlocks in actual code.&lt;/p&gt;
&lt;p&gt;This is because &lt;strong&gt;all&lt;/strong&gt; the Go routines in your entire program have to be asleep for it to trigger and in my experience that almost never happens except in toy examples like these.&lt;/p&gt;
&lt;p&gt;There is always something else going on, like log collection or statistics calculations or something like that which means the race detector does not fire.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-17.png" alt="Slide: Silent deadlock example" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This time if we add one extra go routine as indicated the deadlock detector does not kick in, and the program deadlocks silently.&lt;/p&gt;
&lt;p&gt;Or rather part of the program - process 1 and process 2 - is deadlocked but the rest of it is working fine.&lt;/p&gt;
&lt;p&gt;Unfortunately this is the usual state of affairs when debugging deadlocks – some part of your code just stops working with no other symptoms.&lt;/p&gt;
&lt;p&gt;Enough of your code may be working to give you the idea its it isn’t broken but some important part isn’t progressing.&lt;/p&gt;
&lt;p&gt;We’ll see in the next section of the talk what to do at this point.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-18.png" alt="Slide: Channels and deadlocks" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;A quick diversion, as I expect this question has popped into your minds already.&lt;/p&gt;
&lt;p&gt;Can we use channels instead of those nasty Mutexes to avoid deadlocks?&lt;/p&gt;
&lt;p&gt;Alas, no, you can cause a deadlock with channels just as easily as with Mutexes and we’ll see an example of that later.&lt;/p&gt;
&lt;p&gt;In my my experience with rclone only about 10% of the deadlocks are with channels so they are less likely certainly.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-19.png" alt="Slide: Why deadlocks happen" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;So why do we get deadlocks?&lt;/p&gt;
&lt;p&gt;There are two ingredients.&lt;/p&gt;
&lt;p&gt;The first is concurrency. Without concurrency, that is things happening at the same time, we can’t have deadlocks.&lt;/p&gt;
&lt;p&gt;This means that single threaded code can’t have deadlocks which is a point we’ll come back to later.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-20.png" alt="Slide: Locking causes deadlocks" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The next magic ingredient for deadlocks is locking.&lt;/p&gt;
&lt;p&gt;When I say Locking here I’m including channels. Reading and writing to channels can block your program just as easily as Mutexes.&lt;/p&gt;
&lt;p&gt;And if I wanted to be really precise I’d say shared resource acquisition instead of Locking because you can get deadlocks using other things other than Mutexes and channels, for example using file system locks.&lt;/p&gt;
&lt;p&gt;So where did these locks come from?&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-21.png" alt="Slide: Race detector and locking" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;My excuse is the race detector made me do it :-)&lt;/p&gt;
&lt;p&gt;So what do we do to pacify the race detector? We put locking in, and sooner or later once you’ve put enough locking in you will cause a deadlock.&lt;/p&gt;
&lt;p&gt;I’m joking here of course, the go race detector is wonderful.&lt;/p&gt;
&lt;p&gt;It tells us about data races which would have caused silent corruption in our programs.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-22.png" alt="Slide: Race detector virtues" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Let’s just sing the virtues of the race detector for a moment. It is a technological marvel and very close to magic.&lt;/p&gt;
&lt;p&gt;The race detector will tell you when your program runs a risk of memory corruption due to unsafe accesses.&lt;/p&gt;
&lt;p&gt;If you are writing concurrent programs you should run your tests with the race detector, and if you can, some of your production binaries too.&lt;/p&gt;
&lt;p&gt;Any problems it finds are always real problems – I’ve never known it make a mistake.&lt;/p&gt;
&lt;p&gt;However when fixing the things the race detector points out, do think about what deadlocks you are about to create.&lt;/p&gt;
&lt;p&gt;In particular think about what locks might be already held and what locks you might want to take in this go routine.&lt;/p&gt;
&lt;h2 id="how-to-debug-a-deadlock"&gt;How to debug a deadlock&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-23.png" alt="Slide: File and Directory example" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is an example I’m going to use quite a few times.&lt;/p&gt;
&lt;p&gt;It is a simplified example from rclone’s FUSE based filing system for mounting remote cloud storage as if it were a local disk.&lt;/p&gt;
&lt;p&gt;On the left you can see the definition of the File struct. It has a name, size and a parent directory. It has a Path method which returns the full path of the File and it needs to ask its parent directory for its Path in order to do that. It has a Size method to return its size and a Truncate method showing how the size of the file might get changed.&lt;/p&gt;
&lt;p&gt;On the right we see the definition of the Directory struct. This has a name, a parent directory, a slice of files it contains and a slice of directories it contains. It has a Path method for returning its full path and it needs to find out the Path of its parent here. It also has a Size method which adds up the sizes of all the files in the directory.&lt;/p&gt;
&lt;p&gt;There is no locking in the code above, yet, but a few runs with the race detector reveals that locking is needed.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-24.png" alt="Slide: Adding mutex to File" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;To prevent those nasty data races we add a sync.Mutex called mu into the File structure. The name, lower case mu is traditional in Go code.&lt;/p&gt;
&lt;p&gt;Then in each of the methods we lock the mutex with mu.Lock() and defer the unlock of the mutex with the defer mu.Unlock().&lt;/p&gt;
&lt;p&gt;This means that none of the methods will ever run concurrently and it means our instance variables are safe from data race corruption – hooray!&lt;/p&gt;
&lt;p&gt;This is a standard pattern used in Go concurrent programming and hopefully you’ve seen it before.&lt;/p&gt;
&lt;p&gt;Take the lock at the start of each method and defer its release to the end – what could possibly go wrong?&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-25.png" alt="Slide: Adding mutex to Directory" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;We do the same thing in the Directory structure, add a sync.Mutex called mu to the struct and then call mu.Lock() in each method and defer the mu.Unlock() until the method returns.&lt;/p&gt;
&lt;p&gt;However we’ve unwittingly caused a potential deadlock by doing this.&lt;/p&gt;
&lt;p&gt;I say potential deadlock here because when you run this code it will quite likely work just fine until just the right conditions are met.&lt;/p&gt;
&lt;p&gt;Most deadlocks are like this – they don’t stop your code the first time you create them, they come back to bite you later when you are least expecting them.&lt;/p&gt;
&lt;p&gt;Usually just after you’ve put your code into production.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-26.png" alt="Slide: Provoking the deadlock" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is a bit of code to exercise the Directory and File abstractions and which will provoke the deadlock.&lt;/p&gt;
&lt;p&gt;Process1 just calls File.Path in a loop continuously. Not exactly normal usage, but we’re trying to provoke the deadlock here.&lt;/p&gt;
&lt;p&gt;Process2 just calls Directory.Size in a loop continuously.&lt;/p&gt;
&lt;p&gt;In our main function we create a root directory and put a file into it then start go routines to call process 1 and process 2.&lt;/p&gt;
&lt;p&gt;We also start a race detector defeating go routine which just sleeps for a minute.&lt;/p&gt;
&lt;p&gt;And finally the empty select statement to sleep the main go routine forever. Remember if we exit the main go routine then our program will stop, and we don’t want that.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-27.png" alt="Slide: Sending SIGQUIT" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;So we run the program and it is now sitting there doing a whole heap of nothing while deadlocked.&lt;/p&gt;
&lt;p&gt;How can we find out what it is doing?&lt;/p&gt;
&lt;p&gt;If you are running on a Unix based platform (for example Linux or macOS) then you can send the process a SIGQUIT using the kill command or press Control Backslash. This will produce a nice backtrace.&lt;/p&gt;
&lt;p&gt;Windows platform users will have to work a little harder and install the HTTP debug handler from &lt;a href="https://pkg.go.dev/net/http/pprof"&gt;net/http/pprof&lt;/a&gt; and I’ll show how to do that a bit later.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-28.png" alt="Slide: SIGQUIT backtrace output" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is what happened when I sent the File and Directory example program the QUIT signal.&lt;/p&gt;
&lt;p&gt;I got this nice backtrace. It’s quite long but there is a lot of stuff we can ignore.&lt;/p&gt;
&lt;p&gt;The output is divided into stanzas and at the start of each one is a little description, Here it says goroutine 0, idle.&lt;/p&gt;
&lt;p&gt;Following that is a reference to a line of source code, plus the code itself, once for each level of the call stack.&lt;/p&gt;
&lt;p&gt;In fact this is a system go routine doing something in the runtime – we can ignore it because it doesn’t have any of our code in the backtrace.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-29.png" alt="Slide: Goroutine backtrace analysis" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Next we see go routine 1, select, no cases. This is the wait forever select code which we put in to stop the main function existing. We can ignore this too.&lt;/p&gt;
&lt;p&gt;Next we see go routine 5 semacquire. This one is important, semacquire means it is blocked when trying to acquire a lock. For most deadlocks you are searching for these semacquire lines first.&lt;/p&gt;
&lt;p&gt;Below the semacquire you can see a couple of lines of code in the runtime – these are in the sync.Mutex code, and finally a bit of our code in Dir.Path.&lt;/p&gt;
&lt;p&gt;We can see that Dir.Path was called by File.Path so by the time the go routine tries to acquire the Directory lock it has already acquired the File lock.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-30.png" alt="Slide: Semacquire goroutine blocked" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Next we see goroutine 6 – also blocked on semacquire.&lt;/p&gt;
&lt;p&gt;It looks quite similar to the last one, two lines in sync.Mutex code and then it tring to acquire the mutex in File.Size.&lt;/p&gt;
&lt;p&gt;Looking up the backtrace you can see that File.Size was called from Dir.Size which means that this go routine acquired the Dir lock first and is now blocked on trying to acquire the File lock.&lt;/p&gt;
&lt;p&gt;If you have an editor you can click on those file names to jump to the code in question it is really helpful at this point so you can look up and down the call stack to see what other locks might be held.&lt;/p&gt;
&lt;p&gt;Under that we see go routine 7 sleep which is our deadlock defeating go routine which we can ignore.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-31.png" alt="Slide: Register dump" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;And finally the register dump which you can ignore for this purpose.&lt;/p&gt;
&lt;p&gt;I’m sure the register dump is useful for low level debugging, maybe if you are writing assembler, but I’ve never needed it to debug deadlocks.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-32.png" alt="Slide: Annotated deadlock backtrace" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here I’ve annotated the code from the backtrace showing where each go routine is blocked.&lt;/p&gt;
&lt;p&gt;The fact that both parts of the code are blocked on acquiring a Mutex are very suggestive that there is a deadlock.&lt;/p&gt;
&lt;p&gt;Let’s look at Dir.Path on the left hand side of the screen. We saw from examining the backtraces that this go routine already holds the file lock and is now blocked trying to acquire the directory lock.&lt;/p&gt;
&lt;p&gt;On the right File.Size is already holding the directory lock but is blocked trying to acquire the file lock.&lt;/p&gt;
&lt;p&gt;This means that these two functions are deadlocked and will block forever because the locks they are waiting for will never be released.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-33.png" alt="Slide: Deadlock timeline" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This deadlock occurs whenever the Size method on Dir is called concurrently with the Path method on File.&lt;/p&gt;
&lt;p&gt;When thinking about deadlocks it is helpful to write out a timeline of the two processes involved. The numbers on the left of the code show the ordering of the calls to each process.&lt;/p&gt;
&lt;p&gt;The arrows point from the blocked locks to the place the lock is held, and them crossing is very suggestive of a deadlock.&lt;/p&gt;
&lt;p&gt;You might think that there is very little opportunity for this to happen given the short windows of opportunity – each of these instructions will be over in a few nano seconds won’t it? However, if the deadlock is possible it will happen sooner or later.&lt;/p&gt;
&lt;p&gt;One thing to bear in mind is that locking instructions are particularly slow – they use slow memory locked instructions or schedule go routines or processes - which often turns something you thought would never happen into something which always happens.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-34.png" alt="Slide: HTTP debug handler" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;I’ll just quickly loop back to how to install the HTTP debug handler which you can use to collect backtraces when running Windows.&lt;/p&gt;
&lt;p&gt;Look up the docs for &lt;a href="https://pkg.go.dev/net/http/pprof"&gt;net/http/pprof&lt;/a&gt; – everything you need is in there.&lt;/p&gt;
&lt;p&gt;You can collect the output with curl or just look at in your browser.&lt;/p&gt;
&lt;p&gt;You can use this on any platform of course, and you might consider leaving it in your production code for when your production code has deadlocked and you want to find out why.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-35.png" alt="Slide: HTTP debug handler output" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The output from the HTTP debug handler is similar to the output from SIGQUIT with one stanza for each go routine and a trace showing position in file and the actual line of code being executed.&lt;/p&gt;
&lt;p&gt;It doesn’t call out the state of each go routine in the same way as the SIGQUIT output, but it is easy to see that the two go routines here are each blocked on SemaqcuireMutex which means blocked on acquiring a mutex as you might expect.&lt;/p&gt;
&lt;p&gt;One important difference is that this output collapses goroutines with identical stacks which can very useful if you’ve got 1000s of goroutines.&lt;/p&gt;
&lt;!-- &lt;p&gt;&lt;img src="slide-36.png" alt="Slide" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;img src="long-deadlock-log2.gif" alt="Slide: Long deadlock backtrace" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;When you are tracking down a deadlock in a real world program with lots of concurrency, you’ll find that the backtraces get very long, very quickly.&lt;/p&gt;
&lt;p&gt;Deadlocks have a nasty tendency to spread through a good fraction of your running go routines until they are all waiting on a lock kind of like the way something crystallizes out of a solution.&lt;/p&gt;
&lt;p&gt;Here is an example of an backtrace a user sent me while debugging an rclone deadlock.&lt;/p&gt;
&lt;p&gt;It has nearly 2000 lines covering 260 go routines and is par for the course when dealing with lots of concurrency. There are 14 go routines blocked on acquiring a mutex, 123 blocked in a select statement, 121 blocked on sending or receving to a channel and 1 in a system call and 1 idle.&lt;/p&gt;
&lt;p&gt;If that sounds like looking for a needle in a haystack, it is, we need some help here!&lt;/p&gt;
&lt;!-- &lt;p&gt;&lt;img src="slide-37.png" alt="Slide" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;img src="panicparse_webstack.gif" alt="Slide: Panicparse web output" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Luckily there is a great tool called &lt;a href="https://github.com/maruel/panicparse"&gt;panic parse&lt;/a&gt; which helps enormously here.&lt;/p&gt;
&lt;p&gt;It condenses down that 2000 line log into a nicely coloured 142 line log with one stanza for each different type of go routine.&lt;/p&gt;
&lt;p&gt;It shows that there are only 14 different types of go routine here which makes working out what is going on so much easier.&lt;/p&gt;
&lt;p&gt;It also has a nice web output which I haven’t tried yet, but I’ve put up the screenshot from the github page so you can see what it is like.&lt;/p&gt;
&lt;p&gt;This tool has saved me so much time when debugging deadlocks – thank you Marc-Antoine Ruel!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-38.png" alt="Slide: Panicparse text output" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The text output of panic parse shows a stanza for each go routine. It collapses go routines with similar stacks together like the HTTP debug handler, but better.&lt;/p&gt;
&lt;p&gt;Here is what a stanza looks like. On the left you can see a number – in this case 7 – this is how many go routines like this there were, and really usefully the time it has been paused. Looking for the first goroutine to pause can often be a big clue.&lt;/p&gt;
&lt;p&gt;It is then reasonably easy to see that there are only a few go routines that could possible be the problem, namely the ones that are waiting on locks that have taken locks already so we can immediately ignore nearly all the go routines.&lt;/p&gt;
&lt;p&gt;I’m not going to lie, it’s still tricky working out exactly what the cause of the deadlock from here is, but it is so much easier with panic parse.&lt;/p&gt;
&lt;h2 id="how-to-avoid-deadlocks"&gt;How to avoid deadlocks&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-39.png" alt="Slide: How to avoid deadlocks" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;We’ve talked so far about what a deadlock is and how to find them and debug them, but a better strategy would be to avoid them completely.&lt;/p&gt;
&lt;p&gt;I’m going to talk through a number of different techniques for avoiding deadlocks. Unfortunately there isn’t just one thing I can say – do this and you’ll never get a deadlock again, alas.&lt;/p&gt;
&lt;p&gt;We’re going to start with some easy things to fix then move on to some harder problems.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-40.png" alt="Slide: Channel deadlock example" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;I said there was going to be an example of deadlocks with channels a bit later and here it is!&lt;/p&gt;
&lt;p&gt;Let’s start with a Job. You can see its struct at the top.&lt;/p&gt;
&lt;p&gt;It has a constructor NewJob which doesn’t do a lot in this example.&lt;/p&gt;
&lt;p&gt;The Process method for each job runs the Job. However in the process of running a Job, more Jobs might be created. In this example it picks a random number as to whether to create more jobs or not.&lt;/p&gt;
&lt;p&gt;Those jobs are then returned in a slice for further processing.&lt;/p&gt;
&lt;p&gt;This is simplified from an rclone example where each Job listed a directory and returned jobs to list sub directories.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-41.png" alt="Slide: ProcessJobs function" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here the ProcessJobs function takes a WaitGroup and a channel of jobs. When running it takes a job out of the channel, processes it and adds any created jobs back onto the channel.&lt;/p&gt;
&lt;p&gt;It is written like this with a channel so we can run a few copies of ProcessJobs concurrently to increase the throughput and that is what happens in the main routine -
We start 3 copies of the ProcessJobs function to increase the throughput.&lt;/p&gt;
&lt;p&gt;Its worth explaining what the sync.WaitGroup does here. We are using it to keep track of the number of active jobs – whenever a job is created it is increased with the Add(1) method and whenever a job is finished it is decreased with the Done method.&lt;/p&gt;
&lt;p&gt;When the wait group goes to zero, we know all the jobs have finished and we wait for that moment with the Wait method.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-42.png" alt="Slide: Channel deadlock runs" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;When we run it, it works fine for a while, running jobs, creating new ones, adding them to the channel, until...&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-43.png" alt="Slide: Channel deadlock output" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;… you guessed it, we get a deadlock.&lt;/p&gt;
&lt;p&gt;The first go routine shown, go routine 1, is our sync WaitGroup waiting for the others to finish.&lt;/p&gt;
&lt;p&gt;Goroutine 6, 7 and 8 are all in state chan send. That is they are waiting for a channel to be emptied before they can send some data down it. You can see that they are all waiting in ProcessJobs.&lt;/p&gt;
&lt;p&gt;The problem is that somehow all three of our go routines are blocked writing to the channel and none of them are reading from it.&lt;/p&gt;
&lt;p&gt;Because those 3 go routines are the only place that we read from the channel, it means that the channel will never get emptied and those 3 go routines will never get unblocked, creating a deadlock.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-44.png" alt="Slide: Channel deadlock annotated" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is the code with the deadlock positions marked on it.&lt;/p&gt;
&lt;p&gt;The three ProcessJobs functions are all trying to write a new Job into the jobs channel. However none of them is reading from the channel, so none of those writes will ever succeed A classic deadlock, this time with channels.&lt;/p&gt;
&lt;p&gt;We can also see the sync.Waitgroup Wait method being called to wait for the Job processing to be complete. This is now part of the deadlock too as it will never proceed.&lt;/p&gt;
&lt;p&gt;The Waitgroup Wait isn’t the cause of the deadlock, but it is collateral damage and this is very common when looking at deadlocks. Often the collateral damage overwhelms the cause of the deadlock and that makes it very hard to work out what is going on.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-45.png" alt="Slide: Channel deadlock solution" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;So what is the solution?&lt;/p&gt;
&lt;p&gt;We need the ProcessJobs function to be either reading from the channel or processing a Job. We don’t ever want it to be blocked on writing to the channel, because if one go routine can get blocked then all of them can.&lt;/p&gt;
&lt;p&gt;The easiest way of achieving this is by sending into the channel in a new go routine. The original Go routine is released to receive jobs from the channel while the new go routine sends the new jobs to the channel.&lt;/p&gt;
&lt;p&gt;This has the consequence that there might be an indefinite number of go routines with a few jobs to add to the jobs channel hanging around. If that is a problem then a different design is needed.&lt;/p&gt;
&lt;p&gt;Note we also moved the activeJobs.Done call into the new go routine – we can’t signal a job is finished until all its Job children are safely queued. If we do then the main function will end too early.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-46.png" alt="Slide: Channel deadlock moral" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The moral of this channel deadlock is simple. Don’t send and receive to the same channel in the same go routine – it is a recipe for deadlocks.&lt;/p&gt;
&lt;p&gt;As I said earlier this example came straight from rclone. This dead lock took some time to appear and it took me a few iterations to a find a solution which didn’t deadlock.&lt;/p&gt;
&lt;p&gt;Concurrency is hard!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-47.png" alt="Slide: RWMutex deadlock example" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is an example with read write locks.&lt;/p&gt;
&lt;p&gt;We have two main functions RO and RW. RO takes a read lock then calls MoreRO which in turn takes the Read lock again. This is allowed – read locks can be taken multiple times.&lt;/p&gt;
&lt;p&gt;The RW function takes the lock for Write.&lt;/p&gt;
&lt;p&gt;This look harmless and it works most of the time until suddenly it doesn’t and you made a deadlock as we’ll see in a moment.&lt;/p&gt;
&lt;p&gt;This example is simplified from a real world example which was caused by a bit of careless refactoring.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-48.png" alt="Slide: RWMutex lock step 1" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The next step is the Read Write lock being taken in go routine 2.&lt;/p&gt;
&lt;p&gt;If you read the docs you’ll see a Read Write lock prevents any new Read locks happening so that the lock eventually becomes available.&lt;/p&gt;
&lt;p&gt;There is also a note about recursive locking not being allowed if you read carefully which is exactly what this example is about.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-49.png" alt="Slide: RWMutex lock step 2" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The next step is the Read Write lock being taken in go routine 2.&lt;/p&gt;
&lt;p&gt;If you read the docs you’ll see a Read Write lock prevents any new Read locks happening so that the lock eventually becomes available.&lt;/p&gt;
&lt;p&gt;There is also a note about recursive locking not being allowed if you read carefully which is exactly what this example is about.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-50.png" alt="Slide: RWMutex recursive deadlock" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The deadlock happens when go routine 1 attempts to take the read lock again. This is called recursive locking and none of the standard library locking routines support recursive locking.&lt;/p&gt;
&lt;p&gt;This lock is blocked because the Read Write lock in go routine 2 is in the process of being taken.&lt;/p&gt;
&lt;p&gt;This means that MoreRO function will never return and the RO function will never release its lock, so in its turn the RW function will never acquire the mutex.&lt;/p&gt;
&lt;p&gt;Thus, a deadlock!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-51.png" alt="Slide: RWMutex deadlock moral" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;And the moral of this story is Don’t take a read lock twice in the same go routine.&lt;/p&gt;
&lt;p&gt;It might sound completely obvious but it is really easy to do by accident.&lt;/p&gt;
&lt;p&gt;It does warn explicitly against doing this in the docs too, but of course I didn’t notice that until after I caused this deadlock!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-52.png" alt="Slide: Deadlock commit message" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;I could show a commit message for every one of the examples in this talk, but since we haven’t got all day I’ll just put this one up so you can feel my pain.&lt;/p&gt;
&lt;p&gt;I always find debugging deadlocks hard even with all these nice tools, so when you have to debug one yourself, just remember that!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-53.png" alt="Slide: Interlinked objects deadlock" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Objects which contains locks that call each others methods are a deadlock waiting to happen.&lt;/p&gt;
&lt;p&gt;This happens naturally in more complicated systems, for example file systems, and great care needs to be taken not to cause deadlocks.&lt;/p&gt;
&lt;p&gt;Going back to our Directory and File example, the problem is caused by the fact that Directory and File both call each other’s methods.&lt;/p&gt;
&lt;p&gt;The general solution to this is called Total Lock Ordering but we’re going to look at some easier mitigations first.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-54.png" alt="Slide: Shorten locking window" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is one example fix for the deadlock. I call this technique shortening the locking Window.&lt;/p&gt;
&lt;p&gt;What we’ve done here is released the mutex in the File Path method as soon as we can and in doing that the lock and unlock of the File and Directory mutexes no longer overlap.&lt;/p&gt;
&lt;p&gt;At the top you can see the original function.&lt;/p&gt;
&lt;p&gt;Below that you can see we’ve modified it to make a temporary copy of name and parent from the File then unlocked the mutex.&lt;/p&gt;
&lt;p&gt;This is enough to fix the deadlock as shown before. It does introduce the idea that the Path function might return an out of date Path if the name or parent changes during the call of Path. Some thought is required here as to whether this is OK or not.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-55.png" alt="Slide: Release locks early" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;In order to minimize the chance of deadlocks, release locks as soon as possible to shorten the locking window.&lt;/p&gt;
&lt;p&gt;Specifically release them before calling any other functions or methods which might take locks.&lt;/p&gt;
&lt;p&gt;I’ve even resorted to using the defer statement to defer calls to get them outside the locking of the current method.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-56.png" alt="Slide: Read-only variables" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Another easy mitigation is to notice which members of your object are read only. These should be assigned to once in the initialization of the object and never written again.&lt;/p&gt;
&lt;p&gt;These don’t need any kind of locking at all to access. Concurrent reads are always safe.&lt;/p&gt;
&lt;p&gt;So, for example, here we say that the name of files and their parent directories never change.&lt;/p&gt;
&lt;p&gt;I’ve moved them above the mutex definition to give the idea that they aren’t and don’t need to be protected by the mutex.&lt;/p&gt;
&lt;p&gt;In this rename free world, we don’t need any locking in the Path method and we fixed the deadlock by not having any locking in the File.Path method at all.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-57.png" alt="Slide: No locking needed" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;If you can identify variables which are read only, you don’t need locking for them and they can be accessed outside the lock.&lt;/p&gt;
&lt;p&gt;No locking means no possibility of deadlocks.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-58.png" alt="Slide: Other mitigations" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is a sketch of some other things you can do which I didn’t have room to make examples for.&lt;/p&gt;
&lt;p&gt;Once way to reduce deadlock possibilities is to split the lock into multiple locks, so use more fine grained locking. This makes it less likely the locks will overlap.&lt;/p&gt;
&lt;p&gt;Or maybe you can use atomics for some accesses (perhaps you are incrementing a counter). Atomics never block your process so can’t cause a deadlock. They come with their own caveats so use with care.&lt;/p&gt;
&lt;p&gt;Using a Read write mutex is a great help for reducing lock contention provided you’ve got methods which only read things. Allowing many read only methods to run at once stops them blocking and minimizes the chance of deadlock.&lt;/p&gt;
&lt;p&gt;And if you are using channels, buffered channels help avoid deadlocks because they don’t synchronize two go routines. Deadlocks can still occur when the channels get full though so it wont cure everything.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-59.png" alt="Slide: Total lock ordering" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Now its time to bring out the big guns.&lt;/p&gt;
&lt;p&gt;The ultimate solution to this kind of locking problem is to impose total lock ordering. This means that you are sure that if the locks overlap then you always take one lock first.&lt;/p&gt;
&lt;p&gt;So if you have two locks A and B, you always take lock A before taking lock B in the same go routine. This makes sure we never have a deadlock.&lt;/p&gt;
&lt;p&gt;This, however, is much easier said than done in a structured program with locks inside objects.&lt;/p&gt;
&lt;p&gt;In practice with object based locks and methods, this means making one object super-ordinate and one subordinate.&lt;/p&gt;
&lt;p&gt;For example this might mean that Directory can call File methods with the Directory lock held but File methods &lt;strong&gt;mustn’t&lt;/strong&gt; call Directory methods with the File lock held.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-60.png" alt="Slide: Lock ordering comments" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;In a perfect world we’d be able to specify what we want to a linter. I don’t think such a linter exists yet – if it does do tell! In the mean time comments like this one from rclone are what we have to live with.&lt;/p&gt;
&lt;p&gt;It explains to the reader that the Cache and Item objects are tightly linked and that if you don’t want to cause a deadlock then don’t call Cache methods from Item with the Item lock held.&lt;/p&gt;
&lt;p&gt;This means that when you change code you need to be very careful to uphold those invariants. If you don’t, deadlocks will ensue.&lt;/p&gt;
&lt;p&gt;So make write of comments and do lots of code review when writing this sort of code.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-61.png" alt="Slide: Single threaded engine" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Debugging deadlocks can get very hard, very quickly and I used to think I was pretty good at this computer science stuff, but debugging deadlocks frequently makes me feel very stupid.&lt;/p&gt;
&lt;p&gt;So if the locking gets too complicated then you can bail out and use a single threaded engine to remove &lt;strong&gt;all&lt;/strong&gt; the locking.&lt;/p&gt;
&lt;p&gt;Single threaded likely means lower performance but maybe having no deadlocks is worth it.&lt;/p&gt;
&lt;p&gt;You’d communicate with the engine over channels in a request / response style. Typically you’d send the channel for the response over the request channel.&lt;/p&gt;
&lt;p&gt;This makes things much simpler and is very much in the classic Go style but making everything single threaded will drop your performance which may be unacceptable.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-62.png" alt="Slide: Deadlock detection tools" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;You’ll notice there’s been a lot of struggle with deadlocks in the previous slides and it would be nice if there were tools to help us find the deadlocks before they happen.&lt;/p&gt;
&lt;p&gt;Well there are a couple of notable tools for finding deadlocks in go code.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nickng/dingo-hunter"&gt;Dingo hunter&lt;/a&gt; is based of a theoretical approach for finding channel based deadlocks. You may have caught the talk about it here in 2016. It only works for unbuffered channels, alas, which limits its scope.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/sasha-s/go-deadlock"&gt;Go deadlock&lt;/a&gt; is a practical tool for finding violations of total lock ordering and has been used to find deadlocks in Cockroach DB for example. I’ve used it on the rclone code base a few times.&lt;/p&gt;
&lt;p&gt;It comes up with error messages that look rather like those from the race detector, but unlike the race detector it detects potential deadlocks before they happen so you can run this on your code which hasn’t deadlocked yet.&lt;/p&gt;
&lt;p&gt;Go deadlock only works for mutex deadlocks, not channel deadlocks. As I said before this is probably 90% of the deadlocks I see so it is an excellent start.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-63.png" alt="Slide: Go-deadlock usage" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Go deadlock is very easy to use. Here’s the example from its GitHub page.&lt;/p&gt;
&lt;p&gt;You just replace your sync imports with a go deadlock import and when you run your code it will give total lock ordering errors.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-64.png" alt="Slide: Go-deadlock output" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is what our File and Directory example looks like when run with go deadlock.&lt;/p&gt;
&lt;p&gt;As you can see it nicely points out the potential deadlock. The top half is the first go routine and it’s saying the Directory lock then the File lock was taken but in the other go routine (the bottom half) the File lock was taken first, then the Directory lock. It isn’t saying a deadlock happened, it is just saying that because of this ordering of locks a deadlock could happen.&lt;/p&gt;
&lt;p&gt;I’ve used go-deadlock on more complicated examples and I have to say I’ve found the output quite difficult to interpret. This is because deadlocks are hard to understand rather than a shortcoming of the tool. So if you do plug go deadlock into your massive concurrent program, expect a bit of head scratching while you work out what the error messages mean!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-65.png" alt="Slide: Go-deadlock script" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;When I want to use go deadlock with rclone I run this little script.&lt;/p&gt;
&lt;p&gt;It searches and replaces all the sync Mutex and sync RWMutex with their deadlock detector versions.&lt;/p&gt;
&lt;p&gt;Unfortunately I find you can’t leave Go deadlock in production code as it has too much of a performance impact.&lt;/p&gt;
&lt;p&gt;I’d like to have a neater way of enabling it for testing, but I haven’t figured that out yet.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-66.png" alt="Slide: Conclusion" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This has been quite an intense talk and we’ve gone over a lot of concurrency related things, but I hope you all now have some idea of what a deadlock is, how do debug deadlocks and how to avoid them in the future.&lt;/p&gt;
&lt;p&gt;Deadlocks are the curse of concurrent programming, however there good tools for finding and debugging them and there are some promising tools for helping to prevent them happening in any code base.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-67.png" alt="Slide: Do not panic" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;So if, or rather when, you get to debug your first deadlock, just remember, Don’t Panic, or rather...&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-68.png" alt="Slide: Do panic for backtrace" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;...Do panic and collect a backtrace :-)&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-69.png" alt="Slide: Thank you" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Thank you all very much for listening.&lt;/p&gt;</description></item><item><title>Rclone and Go</title><link>https://ncw.github.io/www/articles/rclone-and-go-2018/</link><pubDate>Wed, 21 Nov 2018 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/rclone-and-go-2018/</guid><description>&lt;p&gt;&lt;img src="slide-01.png" alt="Slide: Title - Rclone and Go" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is a transcript of a talk I gave at the Go London User Group on 2018-11-21. You can &lt;a href="https://youtu.be/L1OLet9qviQ"&gt;watch it on YouTube&lt;/a&gt; (26 minutes) or see the slides and read the words here.&lt;/p&gt;
&lt;p&gt;It's about &lt;a href="https://rclone.org"&gt;rclone&lt;/a&gt; and how rclone uses the &lt;a href="https://golang.org"&gt;Go programming language&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-02.png" alt="Slide: About me" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Good evening.&lt;/p&gt;
&lt;p&gt;I’m Nick Craig-Wood and I’m here to talk about rclone. Rclone is an Open Source command line program to transfer files to and from cloud storage started by me as a hobby in 2012.&lt;/p&gt;
&lt;p&gt;First a bit about me. I’ve loved programming ever since I was 13 with my &lt;a href="https://en.wikipedia.org/wiki/ZX80"&gt;ZX80&lt;/a&gt; and have been doing it ever since.&lt;/p&gt;
&lt;p&gt;Now-a-days I’m CTO of &lt;a href="https://www.memset.com"&gt;Memset Ltd&lt;/a&gt; who do cloud hosting and storage. I don’t get the chance to do a lot of coding at work any more so I now do Open Source coding as a hobby.&lt;/p&gt;
&lt;p&gt;I’ve always had a keen interest in storing data, keeping it safe and transferring it about – hence rclone which is an embodiment of those things!&lt;/p&gt;
&lt;p&gt;I used to be a data hoarder, but the house filled up with servers and disks and my wife complained about the electricity bill so I’m mostly reformed now.&lt;/p&gt;
&lt;p&gt;Thank heavens for cloud storage!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-03.png" alt="Slide: Talk overview" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;My talk this evening is going to start with a quick summary of rclone and its history.&lt;/p&gt;
&lt;p&gt;I’ll dive into how it works, and show a bit of code.&lt;/p&gt;
&lt;p&gt;I’ll then discuss how you test a project like rclone and round off with a look at some of my favourite libraries.&lt;/p&gt;
&lt;p&gt;But before I get going I don’t want you to get the impression rclone is all my work. I’d like to thank my excellent core developers, the super helpful group of people on the forum and anyone who has sent a PR or raised an issue – rclone wouldn’t be what it is today without you.. Oh and thank you for everyone who has sent a PR correcting my spelling :-)&lt;/p&gt;
&lt;h2 id="what-is-rclone"&gt;What is rclone?&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-04.png" alt="Slide: What is rclone" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;In summary rclone is a command line program to sync your data to and from cloud providers.&lt;/p&gt;
&lt;p&gt;Rclone takes lots of care with data integrity, checking hashes at every step and preserves timestamps on your files.&lt;/p&gt;
&lt;p&gt;It can transfer data directly between cloud providers so you can use it to back up your s3 objects to google cloud storage.&lt;/p&gt;
&lt;p&gt;It has some optional features like encryption, but by and large rclone maps objects 1:1 from source to destination.&lt;/p&gt;
&lt;p&gt;There is lots more info on the website.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-05.png" alt="Slide: Rclone and rsync" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Many of you will be familiar with rsync. Which is (see slide)&lt;/p&gt;
&lt;p&gt;Rclone syncing works very much like rsync. I’ve tried to keep the flags the same where possible to make it familiar to rsync users.&lt;/p&gt;
&lt;p&gt;There is one thing rclone does not do though and that is implement the extremely clever delta encoding that rsync uses for transferring objects.&lt;/p&gt;
&lt;p&gt;That unfortunately isn’t possible when trying to copy objects 1:1 to cloud providers as they just don’t provide the API to do it.&lt;/p&gt;
&lt;p&gt;It would be possible to implement it but you’d lose that 1:1 mapping of objects.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-06.png" alt="Slide: Supported providers" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Rclone supports most major cloud providers. Well I think so, they keep making new ones!&lt;/p&gt;
&lt;p&gt;Certainly all the big names are here, both for business use like s3, google cloud storage, azure blob storage and for personal like google drive and dropbox.&lt;/p&gt;
&lt;p&gt;There are also the standard protocols like FTP, SFTP, HTTP.&lt;/p&gt;
&lt;p&gt;I particularly like the HTTP backend – you point it file listing webpage (for example the ones apache generates) and it can pull the files off there recursively, or you can mount it as a disk.&lt;/p&gt;
&lt;p&gt;All rclone operations are supported by all providers.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-07.png" alt="Slide: Platforms and licensing" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Thanks to Go’s amazing cross compiling abilities, rclone runs on nearly every platform you can think of.&lt;/p&gt;
&lt;p&gt;Rclone is licenced under a very liberal MIT licence which means that it gets bundled into Synology NAS and other products like that.&lt;/p&gt;
&lt;p&gt;Nearly all the platforms are cross compiled on a linux host as part of the Travis build. All except Windows and macOS which I had to build natively to fix various problems.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-08.png" alt="Slide: Rclone history" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;As I began to do less programming at work, I realised I needed to do some programming at home in order to retain my sanity.&lt;/p&gt;
&lt;p&gt;In 2012 I decided to learn Go as it had just reached the exciting milestone of a 1.0 release.&lt;/p&gt;
&lt;p&gt;I made a few test programs then I wrote my first major go library, an interface for the openstack swift object storage system.&lt;/p&gt;
&lt;p&gt;I need a program to exercise that “swiftsync” which became “rclone”.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-09.png" alt="Slide: Why Go" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;There were some things that attracted me immediately to Go.&lt;/p&gt;
&lt;p&gt;We’d been using Python a lot at work so the single binary for a deployment was just breath of fresh air.&lt;/p&gt;
&lt;p&gt;Go excels in concurrency which is really important for rclone too. Everything works concurrently in rclone such as directory listings and transfers of objects.&lt;/p&gt;
&lt;p&gt;I started using Go as a new challenge and it has really brought back the joy of programming for me personally.&lt;/p&gt;
&lt;p&gt;Lastly Go is a really easy language to pick up, especially if you’ve done any programming in a language similar to C such as Java.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-10.png" alt="Slide: Rclone growth stats" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;From its humble beginnings rclone has grown into quite a large project.&lt;/p&gt;
&lt;p&gt;As of today we’ve got about 11,000 stars on github, 200 contributors who’ve made 500 pull requests. Rclone get’s downloaded quarter of a million times a month and it has been packaged by the major Linux, Windows and Mac distributions.&lt;/p&gt;
&lt;p&gt;Exactly how rclone got all those users is a mystery, but being on the front page of Hacker news added about 1,000 github stars overnight. Unfortunately at that time I was in the Outer Hebrides with no Internet so I had no idea this was happening!&lt;/p&gt;
&lt;p&gt;
&lt;video controls style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;
&lt;source src="../../pub/rclone/rclone-gource-visualisation-2.mp4" type="video/mp4"&gt;
Sorry, your browser doesn't support embedded videos.
&lt;/video&gt;
&lt;/p&gt;
&lt;p&gt;Here is a visualisation of rclone’s source code made with Gource.&lt;/p&gt;
&lt;p&gt;Rclone was created in 2012 and it got off to a slow start with just me – that is me whizzing about.&lt;/p&gt;
&lt;p&gt;Rclone reached v1.00 in 2014 and supported 3 backends: s3, drive and swift.&lt;/p&gt;
&lt;p&gt;Rclone gained its first external contribution in 2015. That was when it implemented Amazon Drive and it started to get popular.&lt;/p&gt;
&lt;p&gt;In 2016 it gained some traditional protocols, SFTP and FTP and by 2017 I’d finally figured out I needed a VFS layer. Which brings us to the frenzy of 2018!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-12.png" alt="Slide: Amazon Drive incident" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;In 2017 I was surprised to find rclone in the middle of a minor media storm.&lt;/p&gt;
&lt;p&gt;This is how...In 2015 Amazon launched their Unlimited Drive Storage product.&lt;/p&gt;
&lt;p&gt;This, for a certain kind of person that you can find on the data hoarders subreddit was a personal challenge as you can imagine.&lt;/p&gt;
&lt;p&gt;The screenshot on the left was sent to me from that reddit and all the data (1 Peta byte of it) was uploaded with rclone.&lt;/p&gt;
&lt;p&gt;Rclone was banned from Amazon Cloud Drive, probably as a consequence of this, though ostensibly it was the use of encrypted keys within the binary. Amazon also shut down the unlimited Drive product in the US&lt;/p&gt;
&lt;p&gt;I was surprised to have an interview with a journalist from The Register.&lt;/p&gt;
&lt;p&gt;Rclone is still banned from Amazon Cloud Drive unless you have your own keys.&lt;/p&gt;
&lt;h2 id="how-does-it-work"&gt;How does it work?&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-13.png" alt="Slide: How rclone works" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;I’ll now move on from the history to how it works.&lt;/p&gt;
&lt;p&gt;There are a number different functionalities of rclone. Each of these is implemented as a sub command otherwise known as a verb of the main program.&lt;/p&gt;
&lt;p&gt;You write the verbs after the command so “rclone config” or “rclone sync”. More parameters can come after the verb.&lt;/p&gt;
&lt;p&gt;For data transfer the main 3 verbs are sync, copy and move.&lt;/p&gt;
&lt;!-- &lt;p&gt;&lt;img src="slide-14.png" alt="Slide" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;img src="rclone-config.gif" alt="Slide: Rclone config demo" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The first command you run after installing rclone is “rclone config”.&lt;/p&gt;
&lt;p&gt;This starts up the old school config wizard.&lt;/p&gt;
&lt;p&gt;I think I first saw this style of config wizard in perl when configuring CPAN.&lt;/p&gt;
&lt;p&gt;It isn’t the prettiest in the world but it gets the job done!&lt;/p&gt;
&lt;p&gt;When it needs to do oauth it opens up your browser for you and redirects back to a local webserver to receive the results.&lt;/p&gt;
&lt;!-- &lt;p&gt;&lt;img src="slide-15.png" alt="Slide" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;img src="rclone-copy.gif" alt="Slide: Rclone copy demo" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The next thing you are likely to want to do is copy some files.&lt;/p&gt;
&lt;p&gt;Here is a quick demo of some files being copied using “rclone copy” and “rclone ls” to list the files.&lt;/p&gt;
&lt;p&gt;Always start with “rclone copy” - don’t use “rclone sync” as that can delete files in the destination.&lt;/p&gt;
&lt;!-- &lt;p&gt;&lt;img src="slide-16.png" alt="Slide" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;img src="rclone-sync.gif" alt="Slide: Rclone sync demo" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This shows the use of rclone sync.&lt;/p&gt;
&lt;p&gt;Rclone sync differs from copy in that it makes the source and destination identical.&lt;/p&gt;
&lt;p&gt;This means that it copies files to the destination and deletes any files in the destination which should be there.&lt;/p&gt;
&lt;p&gt;Always try with –dry-run first!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-17.png" alt="Slide: Rclone copy diagram" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is rclone copy in diagram format.&lt;/p&gt;
&lt;p&gt;On the left are the source and destination before the command and on the right after the command.&lt;/p&gt;
&lt;p&gt;You can see that it can copy a file, ignore an unchanged file, overwrite a stale file and that it doesn’t touch files which exist in the destination already but aren’t in the source.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-18.png" alt="Slide: Rclone sync diagram" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Whereas rclone sync’s job is to get the source and destination identical&lt;/p&gt;
&lt;p&gt;You can see that it can copy a file, ignore an unchanged file, overwrite a stale file and that it deletes files which exist in the destination already but aren’t in the source.&lt;/p&gt;
&lt;p&gt;Rclone sync, copy and move are all implemented by the same routine as most of the code is identical between them.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-19.png" alt="Slide: Rclone mount" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Rclone mount is one of my favourite features. Mount any backend supported by rclone as a FUSE mount.&lt;/p&gt;
&lt;p&gt;This works on linux, mac and Windows.&lt;/p&gt;
&lt;p&gt;Rclone supports seeking on the files too so you can play video quite well from your cloud storage system and I know that lots of rclone users do exactly this.&lt;/p&gt;
&lt;p&gt;However if you want to open a file for both read and write or seek while writing then rclone will need to download the file and work on a cached copy. This is part of the VFS layer in rclone which adapts rclone objects to work more like an actual file system.&lt;/p&gt;
&lt;!-- &lt;p&gt;&lt;img src="slide-20.png" alt="Slide" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;img src="rclone-ncdu.gif" alt="Slide: Rclone ncdu demo" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is another of my favourite features.&lt;/p&gt;
&lt;p&gt;It is a blatant rip-off or homage as I prefer to call it of the ncdu tool. If you’ve never used it I recommend you install it right away&lt;/p&gt;
&lt;p&gt;It is the best tool for answering the question “Where is all my disk space?”. It lets you explore your local disk using a really easy to use curses interface.&lt;/p&gt;
&lt;p&gt;I had the idea of implementing that in rclone and I needed something to do on a plane journey so hence rclone ncdu was born.&lt;/p&gt;
&lt;p&gt;It uses the excellent termbox library to implement the text based user interface.&lt;/p&gt;
&lt;h2 id="dive-into-code"&gt;Dive into code&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-21.png" alt="Slide: Backend Fs interface" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Now let’s dive into a bit of code.&lt;/p&gt;
&lt;p&gt;Rclone implements its backends using interfaces which won’t be a suprise. This shows the interface which all rclone backends must fulfil.&lt;/p&gt;
&lt;p&gt;Rob Pike tells us: “The bigger the interface, the weaker the abstraction” - this is a big interface :-(&lt;/p&gt;
&lt;p&gt;It is broken down into 3 sub parts in the rclone source but I’ve presented the whole interface here as it all as to be implemented for a backend.&lt;/p&gt;
&lt;p&gt;You can see the kind of methods you might expect, List, NewObject, Put and Mkdir.&lt;/p&gt;
&lt;p&gt;There are also some missing from that list which I’ll cover in a moment, like Copy.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-22.png" alt="Slide: Object interface" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is the interface a cloud storage object must fulfil.&lt;/p&gt;
&lt;p&gt;Again pretty straight forward. Note the Hash method which you call with one of the types the Hashes method in the Fs object returns.&lt;/p&gt;
&lt;p&gt;Open reads the object and Update sets its contents.&lt;/p&gt;
&lt;p&gt;You can also read the modification time and set the modification time – something that is very important for rclone syncing.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-23.png" alt="Slide: Optional interfaces" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;All the backends support the interfaces in the previous two slides. However some backends can do more, and rclone can use that.&lt;/p&gt;
&lt;p&gt;For example the Purge interface deletes a directory and everything under it. Some backends can do that and some can’t.&lt;/p&gt;
&lt;p&gt;For example, say you were doing a server side move of an object. Some backends can do that immediately with the Move method (for example Google Drive). Some support Copy but not Move (for example S3). Rclone will Copy the object then Delete it. And some don’t support either (eg B2) in which case rclone will download the object and upload it again.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-24.png" alt="Slide: Type assertions" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Here is how you might use those optional interfaces – with an type assertion. That is straight forward go code.&lt;/p&gt;
&lt;p&gt;However, rclone backends can wrap other backends, for example the encryption backend. The outer backend wants to expose what the inner backend can do so must implement all optional methods. The inner backend may not implement all optional methods so we’ve got a problem.&lt;/p&gt;
&lt;p&gt;The traditional solution to this is a sentinel error which we check. Here we call Purge and check the err value against ErrCantPurge.&lt;/p&gt;
&lt;p&gt;This works very well, provided you don’t want to know which methods are used in advance. Unfortunately rclone does need to know….&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-25.png" alt="Slide: Features struct" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The solution to that is a good old fashioned struct full of function pointers. This is filled in with a bit of reflection so doesn’t take any manual work to keep up to date.&lt;/p&gt;
&lt;p&gt;Backends which wrap other backends logical AND their own features with the features of the wrapped backend to make the final Features struct.&lt;/p&gt;
&lt;p&gt;To use Purge, say, you just check to see if the pointer is nil. If it isn’t nil that means the method is supported so you can call it.&lt;/p&gt;
&lt;p&gt;Those of you who’ve used C++ will realise this is a re-implementation of the vtable or virtual table. Go made the implementation straight forward though.&lt;/p&gt;
&lt;h2 id="testing"&gt;Testing&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-26.png" alt="Slide: Testing overview" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Lets go into how rclone is tested.&lt;/p&gt;
&lt;p&gt;As you saw earlier rclone supports lots of providers, it has lots of commands, architectures OSes. That all makes it really hard to test.&lt;/p&gt;
&lt;p&gt;Anyone think writing mocks for 27 different cloud providers would be much fun for a hobby project? No?&lt;/p&gt;
&lt;p&gt;So rclone does lots of integration tests. These give real confidence that rclone works properly and keeps on working. After all cloud providers often change stuff.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-27.png" alt="Slide: CI pipeline" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Rclone has a full continuous integration pipeline.&lt;/p&gt;
&lt;p&gt;I think we are amazingly lucky as open source programmers to be able to use Github, Travis and Appveyor for free – they are fantastic tools.&lt;/p&gt;
&lt;p&gt;The CI tests run all the non integration tests and builds binaries for all the platforms, uploading them for beta release automatically for every branch pushed to the main repository.&lt;/p&gt;
&lt;p&gt;You’ll find those at beta.rclone.org&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-28.png" alt="Slide: Integration tests" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The integration tests run on a separate server.&lt;/p&gt;
&lt;p&gt;These run the tests, which are just normal go unit tests with some extra flags against all the backends.&lt;/p&gt;
&lt;p&gt;Running these tests costs money and takes a long time so I don’t run them against every pull request, only against the master branch and only once per day.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-29.png" alt="Slide: Test report" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The integration tests produce a report for the developers to look at.&lt;/p&gt;
&lt;p&gt;This was a good day with only one failure out of 105 tests.&lt;/p&gt;
&lt;p&gt;Often there are lots of failures, usually because of some cloud provider glitch, but sometimes because of a change in the rclone code.&lt;/p&gt;
&lt;p&gt;Making a pretty report (well that is pretty by my standards) wasn’t high on my priority list. However I completely messed up one of the releases by misreading the old report, so I made a report which couldn’t be misunderstood.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-30.png" alt="Slide: Test framework" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;The integration tests rclone uses are standard go tests. It is easy to add flags to the go tests and rclone adds a “-remote” flag to tell it to run the tests against an actual backend.&lt;/p&gt;
&lt;p&gt;Unlike unit tests, integration tests often fail. The internet is a messy place – things go wrong. The test_all framework re-runs the tests that fails to try to get them to pass.&lt;/p&gt;
&lt;p&gt;I should probably take the time to open source this framework as it could be useful elsewhere!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-31.png" alt="Slide: Nested tests" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;In go1.6 the concept of nested tests was introduced.&lt;/p&gt;
&lt;p&gt;This made rclone’s life much easier. As you can see it is only a few lines of code to run the integration test suite for a backend. Some backends run the suite more than once with different parameters.&lt;/p&gt;
&lt;p&gt;When making a new backend, you can use the integration tests as a guide for what you need to work on next and it makes the process quite enjoyable.&lt;/p&gt;
&lt;p&gt;Pre go1.6 code generation was used to make the integration tests which was rather painful so thank you to the Go team for making nested tests.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-32.png" alt="Slide: Test flags" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;This is something that not many people know, but can make your life much easier.&lt;/p&gt;
&lt;p&gt;You can add flags to tests. You don’t need to do anything special, just define flags with the standard library flag package.&lt;/p&gt;
&lt;p&gt;There are some great examples of this in the standard library, for instance using a “-golden” flag to make the tests files.&lt;/p&gt;
&lt;p&gt;Rclone uses flags to indicate that tests should run with a real backend, and to help debug those tests.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-33.png" alt="Slide: Code statistics" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Rclone is a reasonably large program now, approaching 100 thousand lines of Go code.&lt;/p&gt;
&lt;p&gt;However it is built on a fantastic set of libraries some of which I’ll talk about in a moment.&lt;/p&gt;
&lt;p&gt;And all of that in turn is built on the go standard library.&lt;/p&gt;
&lt;p&gt;Rclone uses the vendor directory to keep that all straight, and we recently switched to “go mod” to manage that.&lt;/p&gt;
&lt;p&gt;I don’t think we can drop the vendor directory just yet as rclone needs to support old go versions for the Linux distros that package rclone. Maybe in a year or two.&lt;/p&gt;
&lt;h2 id="tools"&gt;Tools&lt;/h2&gt;
&lt;!-- &lt;p&gt;&lt;img src="slide-34.png" alt="Slide" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;img src="goimports.gif" alt="Slide: Goimports demo" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;I’ll just run through a few of my favourite libraries and tools that rclone uses.&lt;/p&gt;
&lt;p&gt;There are loads of other libraries I could have mentioned here so apologies to any authors I’ve missed out.&lt;/p&gt;
&lt;p&gt;My first choice is goimports. Install it in your editor and never type an import statement again.&lt;/p&gt;
&lt;p&gt;You can see me editing a small file in emacs here and the import statements being automatically added while the code is formatted for you. It works in vim too so I’m told ;-)&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-35.png" alt="Slide: Cobra library" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Cobra is excellent for organising command line programs with lots of verbs.&lt;/p&gt;
&lt;p&gt;I’m sure many of you have used kubectl to control kubernetes or used docker – that is cobra in action.&lt;/p&gt;
&lt;p&gt;Cobra comes with a flag library pflag which allows you to create POSIX flags. Flags made by the go flag library are somewhat old school in comparison.&lt;/p&gt;
&lt;p&gt;Cobra also creates your bash completion script for all those people like me who use bash, but hate writing bash scripts!&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-36.png" alt="Slide: Cobra documentation" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Cobra helps with the documentation. When you write a command cobra makes command help for it and then has a really easy way of turning that into markdown for the website.&lt;/p&gt;
&lt;p&gt;A lot of the help on the rclone website was generated this way and it really helps keeping everything consistent.&lt;/p&gt;
&lt;p&gt;I then use pandoc to turn the markdown into a man page and one big HTML document for the download.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-37.png" alt="Slide: Error handling" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;If you’ve been keeping up with go news you’ll have read the errors proposal for go 2.&lt;/p&gt;
&lt;p&gt;The pkg/errors package was one of the motivations for the proposal, so I imagine at some time I’ll be retiring it when go 2 comes along.&lt;/p&gt;
&lt;p&gt;You use it to annotate your errors as they bubble up through your code.&lt;/p&gt;
&lt;p&gt;This means that rather than receiving a log message with “unexpected EOF” you receive a helpful message which gives you some idea as to what really went wrong.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-38.png" alt="Slide: Open source tips" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;I’m just going to talk briefly about what to do if your open source package takes off.&lt;/p&gt;
&lt;p&gt;It is easy to get daunted by 100s of issues most of which are support requests so the first thing to do is open a forum and get the users helping themselves. I use Discourse – it is free and easy to setup and maintain.&lt;/p&gt;
&lt;p&gt;Don’t be shy of asking users who make issues for help. You might need to give them a bit of a helping hand, but that is a positive process for both parties.&lt;/p&gt;
&lt;p&gt;When you’ve had a few good pull requests from someone, recruit them!&lt;/p&gt;
&lt;p&gt;Oh yes, write lots of docs – maybe that should have gone first.&lt;/p&gt;
&lt;p&gt;Finally get octobox.io – rather than managing 100s of emails from Github manage them in a nice web interface where you can filter etc.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-39.png" alt="Slide: Thank you" style="width: 80%; height: auto; border: 5px solid #555; border-radius: 15px;"&gt;&lt;/p&gt;
&lt;p&gt;Thank you all for listening :-)&lt;/p&gt;</description></item><item><title>Snake Puzzle Solver</title><link>https://ncw.github.io/www/articles/snake-puzzle/</link><pubDate>Sun, 25 Sep 2016 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/snake-puzzle/</guid><description>&lt;p&gt;My family know I like puzzles so they gave me this one recently:&lt;/p&gt;
&lt;div class="card float-right" style="max-width: 18rem;"&gt;
&lt;div class="card-header" style="padding: 5px 10px;"&gt;
Fork me on Github
&lt;/div&gt;
&lt;div class="card-body"&gt;
The code for this along with a Jupyter notebook for it is &lt;a href="https://github.com/ncw/snake-puzzle/"&gt;on
github&lt;/a&gt;.
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="snake-puzzle-boxed.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;When you take it out the box it looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="snake-puzzle-solved.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;And very soon after it looked like this (which explains why I've
christened the puzzle &amp;quot;the snake puzzle&amp;quot;):&lt;/p&gt;
&lt;p&gt;&lt;img src="snake-puzzle-flat.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The way it works is that there is a piece of elastic running through
each block. On the majority of the blocks the elastic runs straight
through, but on some of the it goes through a 90 degree bend. The puzzle
is trying to make it back into a cube.&lt;/p&gt;
&lt;p&gt;After playing with it a while, I realised that it really is quite hard
so I decided to write a program to solve it.&lt;/p&gt;
&lt;p&gt;The first thing to do is find a representation for the puzzle. Here is
the one I chose:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# definition - number of straight bits, before 90 degree bend&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;snake &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;assert&lt;/span&gt; sum(snake) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you look at the picture of it above where it is flattened you can see
where the numbers came from. Start from the right hand side.&lt;/p&gt;
&lt;p&gt;That also gives us a way of calculating how many combinations there are.
At each 90 degree joint, there are 4 possible rotations (ignoring the
rotations of the 180 degree blocks) so there are:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#f92672"&gt;**&lt;/span&gt;len(snake)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;17179869184&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;17 billion combinations. That will include some rotations and
reflections, but either way it is a big number.&lt;/p&gt;
&lt;p&gt;However it is very easy to know when you've gone wrong with this kind
of puzzle - as soon as you place a piece outside of the boundary of the
3x3x3 block you know it is wrong and should try something different.&lt;/p&gt;
&lt;p&gt;So how to represent the solution? The way I've chosen is to represent
it as a 5x5x5 cube. This is larger than it needs to be but if we fill in
the edges then we don't need to do any complicated comparisons to see
if a piece is out of bounds. This is a simple trick but it saves a lot
of code.&lt;/p&gt;
&lt;p&gt;I've also chosen to represent the 3d structure not as a 3d array but as
a 1D array (or &lt;code&gt;list&lt;/code&gt; in python speak) of length 5 x 5 x 5 = 125.&lt;/p&gt;
&lt;p&gt;To move in the &lt;code&gt;x&lt;/code&gt; direction you add 1, to move in the &lt;code&gt;y&lt;/code&gt; direction you
add 5 and to move in the &lt;code&gt;z&lt;/code&gt; direction you move 25. This simplifies the
logic of the solver considerably - we don't need to deal with vectors.&lt;/p&gt;
&lt;p&gt;The basic definitions of the cube look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;N &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xstride&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#75715e"&gt;# number of pieces to move in the x direction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ystride&lt;span style="color:#f92672"&gt;=&lt;/span&gt;N &lt;span style="color:#75715e"&gt;# number of pieces to move in the y direction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;zstride&lt;span style="color:#f92672"&gt;=&lt;/span&gt;N&lt;span style="color:#f92672"&gt;*&lt;/span&gt;N &lt;span style="color:#75715e"&gt;# number of pieces to move in the z direction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In our &lt;code&gt;list&lt;/code&gt; we will represent empty space with &lt;code&gt;0&lt;/code&gt; and space which
can't be used with &lt;code&gt;-1&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;empty &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now define the empty cube with the boundary round the edges:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Define cube as 5 x 5 x 5 with filled in edges but empty middle for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# easy edge detection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;top &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;*&lt;/span&gt;N&lt;span style="color:#f92672"&gt;*&lt;/span&gt;N
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;middle &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; [&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; [&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cube &lt;span style="color:#f92672"&gt;=&lt;/span&gt; top &lt;span style="color:#f92672"&gt;+&lt;/span&gt; middle&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; top
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We're going to want a function to turn &lt;code&gt;x, y, z&lt;/code&gt; co-ordinates into an
index in the &lt;code&gt;cube&lt;/code&gt; list:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pos&lt;/span&gt;(x, y, z):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;Convert x,y,z into position in cube list&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x&lt;span style="color:#f92672"&gt;+&lt;/span&gt;y&lt;span style="color:#f92672"&gt;*&lt;/span&gt;ystride&lt;span style="color:#f92672"&gt;+&lt;/span&gt;z&lt;span style="color:#f92672"&gt;*&lt;/span&gt;zstride
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So let's see what that cube looks like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;print_cube&lt;/span&gt;(cube, margin&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;Print the cube&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; z &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(margin,N&lt;span style="color:#f92672"&gt;-&lt;/span&gt;margin):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; y &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(margin,N&lt;span style="color:#f92672"&gt;-&lt;/span&gt;margin):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; x &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(margin,N&lt;span style="color:#f92672"&gt;-&lt;/span&gt;margin):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v &lt;span style="color:#f92672"&gt;=&lt;/span&gt; cube[pos(x,y,z)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; v &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; s &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34; . &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; s &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%02d&lt;/span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; v
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(s, sep&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, end&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; print_cube(cube, margin &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Normally we'll print it without the margin.&lt;/p&gt;
&lt;p&gt;Now let's work out how to place a segment.&lt;/p&gt;
&lt;p&gt;Assuming that the last piece was placed at &lt;code&gt;position&lt;/code&gt; we want to place a
segment of &lt;code&gt;length&lt;/code&gt; in &lt;code&gt;direction&lt;/code&gt;. Note the &lt;code&gt;assert&lt;/code&gt; to check we
aren't placing stuff on top of previous things, or out of the edges:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;place&lt;/span&gt;(cube, position, direction, length, piece_number):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;Place a segment in the cube&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; _ &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(length):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; direction
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;assert&lt;/span&gt; cube[position] &lt;span style="color:#f92672"&gt;==&lt;/span&gt; empty
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cube[position] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; piece_number
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; piece_number &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; position
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let's just try placing some segments and see what happens:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; cube2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; cube[:] &lt;span style="color:#75715e"&gt;# copy the cube&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; place(cube2, pos(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), xstride, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; print_cube(cube2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; place(cube2, pos(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), ystride, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; print_cube(cube2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; place(cube2, pos(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), zstride, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; print_cube(cube2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;06&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The next thing we'll need is to undo a place. You'll see why in a
moment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;unplace&lt;/span&gt;(cube, position, direction, length):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;Remove a segment from the cube&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; _ &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(length):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; direction
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cube[position] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; empty
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; unplace(cube2, pos(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), zstride, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; print_cube(cube2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let's write a function which returns whether a move is valid given
a current &lt;code&gt;position&lt;/code&gt; and a &lt;code&gt;direction&lt;/code&gt; and a &lt;code&gt;length&lt;/code&gt; of the segment we
are trying to place.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;is_valid&lt;/span&gt;(cube, position, direction, length):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;Returns True if a move is valid&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; _ &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(length):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; direction
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; cube[position] &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; empty:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; is_valid(cube2, pos(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), zstride, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; is_valid(cube2, pos(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), zstride, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Given &lt;code&gt;is_valid&lt;/code&gt; it is now straight forward to work out what moves are
possible at a given time, given a &lt;code&gt;cube&lt;/code&gt; with a &lt;code&gt;position&lt;/code&gt;, a
&lt;code&gt;direction&lt;/code&gt; and a &lt;code&gt;length&lt;/code&gt; we are trying to place.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# directions next piece could go in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;directions &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [xstride, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;xstride, ystride, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;ystride, zstride, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;zstride]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;moves&lt;/span&gt;(cube, position, direction, length):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;Returns the valid moves for the current position&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; valid_moves &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; new_direction &lt;span style="color:#f92672"&gt;in&lt;/span&gt; directions:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Can&amp;#39;t carry on in same direction, or the reverse of the same direction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; new_direction &lt;span style="color:#f92672"&gt;==&lt;/span&gt; direction &lt;span style="color:#f92672"&gt;or&lt;/span&gt; new_direction &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;direction:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; is_valid(cube, position, new_direction, length):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; valid_moves&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(new_direction)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; valid_moves
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; moves(cube2, pos(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), ystride, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So that is telling us that you can insert a segment of length 2 using a
direction of &lt;code&gt;-xstride&lt;/code&gt; or &lt;code&gt;zstride&lt;/code&gt;. If you look at previous
&lt;code&gt;print_cube()&lt;/code&gt; output you'll see those are the only possible moves.&lt;/p&gt;
&lt;p&gt;Now we have all the bits to build a recursive solver.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;solve&lt;/span&gt;(cube, position, direction, snake, piece_number):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;Recursive cube solver&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(snake) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;Solution&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print_cube(cube)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; length, snake &lt;span style="color:#f92672"&gt;=&lt;/span&gt; snake[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;], snake[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; valid_moves &lt;span style="color:#f92672"&gt;=&lt;/span&gt; moves(cube, position, direction, length)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; new_direction &lt;span style="color:#f92672"&gt;in&lt;/span&gt; valid_moves:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_position &lt;span style="color:#f92672"&gt;=&lt;/span&gt; place(cube, position, new_direction, length, piece_number)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; solve(cube, new_position, new_direction, snake, piece_number&lt;span style="color:#f92672"&gt;+&lt;/span&gt;length)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; unplace(cube, position, new_direction, length)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works by being passed in the &lt;code&gt;snake&lt;/code&gt; of moves left. If there are no
moves left then it must be solved, so we print the solution. Otherwise
it takes the head off the &lt;code&gt;snake&lt;/code&gt; with
&lt;code&gt;length, snake = snake[0], snake[1:]&lt;/code&gt; and makes the list of valid moves
of that &lt;code&gt;length&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then we &lt;code&gt;place&lt;/code&gt; each move, and try to &lt;code&gt;solve&lt;/code&gt; that cube using a
recursive call to &lt;code&gt;solve&lt;/code&gt;. We &lt;code&gt;unplace&lt;/code&gt; the move so we can try again.&lt;/p&gt;
&lt;p&gt;This very quickly runs through all the possible solutions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Start just off the side&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;position &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pos(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;direction &lt;span style="color:#f92672"&gt;=&lt;/span&gt; xstride
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;length &lt;span style="color:#f92672"&gt;=&lt;/span&gt; snake[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Place the first segment along one edge - that is the only possible place it can go&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;position &lt;span style="color:#f92672"&gt;=&lt;/span&gt; place(cube, position, direction, length, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Now solve!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;solve(cube, position, direction, snake[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:], length&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Solution
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;06&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Solution
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;07&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;06&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;09&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wow! It came up with 2 solutions! However they are the same solution
just rotated and reflected.&lt;/p&gt;
&lt;p&gt;But how do you use the solution? Starting from the correct end of the
snake, place each piece into its corresponding number. Take the first
layer of the solution as being the bottom (or top - whatever is
easiest), the next layer is the middle and the one after the top.&lt;/p&gt;
&lt;p&gt;&lt;img src="snake-puzzle-flat-numbered.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;After a bit of fiddling around you'll get...&lt;/p&gt;
&lt;p&gt;&lt;img src="snake-puzzle-solved.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;I hope you enjoyed that introduction to puzzle solving with computer.&lt;/p&gt;
&lt;p&gt;If you want to try one yourselves, use the same technique to solve
solitaire.&lt;/p&gt;
&lt;p&gt;Download the entire code
&lt;a href="snake_puzzle_solver.py"&gt;snake_puzzle_solver.py&lt;/a&gt; or the &lt;a href="snake_puzzle_solver.ipynb"&gt;iPython
notebook&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>IOCCC 2012 Mersenne Prime Checker</title><link>https://ncw.github.io/www/articles/ioccc-2012-mersenne-prime-checker/</link><pubDate>Wed, 03 Oct 2012 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/ioccc-2012-mersenne-prime-checker/</guid><description>&lt;p&gt;This was my entry for the 20&lt;sup&gt;th&lt;/sup&gt; &lt;a href="http://www.ioccc.org/"&gt;International Obfuscated C Code
Contest&lt;/a&gt;, a contest whose aims are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To write the most Obscure/Obfuscated C program under the rules.&lt;/li&gt;
&lt;li&gt;To show the importance of programming style, in an ironic way.&lt;/li&gt;
&lt;li&gt;To stress C compilers with unusual code.&lt;/li&gt;
&lt;li&gt;To illustrate some of the subtleties of the C language.&lt;/li&gt;
&lt;li&gt;To provide a safe forum for poor C code. :-)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've been meaning to enter the contest for quite a few years so was
very pleased to see it re-opened for 2012.&lt;/p&gt;
&lt;p&gt;Alas my entry didn't win, but maybe you'll enjoy the entry and
explanation.&lt;/p&gt;
&lt;p&gt;Here is my entry:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;inttypes.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define H uint32_t
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define U uint64_t
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define N void
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define T int
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define P calloc(n,sizeof(U))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define R return
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define I for(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define M if(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define E &amp;gt;&amp;gt;32
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define S i=0;i&amp;lt;n;i++)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; U K&lt;span style="color:#f92672"&gt;=-&lt;/span&gt;(U)(H)&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#f92672"&gt;*&lt;/span&gt;B,&lt;span style="color:#f92672"&gt;*&lt;/span&gt;C
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ,&lt;span style="color:#f92672"&gt;*&lt;/span&gt;x,AC,h;T L,n,F,l,p,D,&lt;span style="color:#f92672"&gt;*&lt;/span&gt;_;U &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;(U x,U
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; y){x&lt;span style="color:#f92672"&gt;=&lt;/span&gt;K&lt;span style="color:#f92672"&gt;-&lt;/span&gt;x;U r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;y&lt;span style="color:#f92672"&gt;-&lt;/span&gt;x;M y&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;x)r&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;K;R r;}U &lt;span style="color:#a6e22e"&gt;AB&lt;/span&gt;(U x,H
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; w,U&lt;span style="color:#f92672"&gt;*&lt;/span&gt;c){U s&lt;span style="color:#f92672"&gt;=&lt;/span&gt;x&lt;span style="color:#f92672"&gt;+*&lt;/span&gt;c;H t&lt;span style="color:#f92672"&gt;=&lt;/span&gt;s&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;x;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;(s&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;w)&lt;span style="color:#f92672"&gt;+&lt;/span&gt;(t&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;w));R
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; s&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;((((U)&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;w)&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ) ;} U &lt;span style="color:#a6e22e"&gt;Q&lt;/span&gt;(U x,U y ) {U r
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;x&lt;span style="color:#f92672"&gt;-&lt;/span&gt;y;M x&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;y)r&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;K;R r;} U &lt;span style="color:#a6e22e"&gt;AD&lt;/span&gt;(U b,U
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a){H d&lt;span style="color:#f92672"&gt;=&lt;/span&gt;b E,c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;b;M a &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; K)a&lt;span style="color:#f92672"&gt;-=&lt;/span&gt; K;a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Q&lt;/span&gt;(a,c);a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Q&lt;/span&gt;(a,d) ;a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt; (a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ,((U)c)&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;);R a;}U &lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;( U
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x,U y){H a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;x,b&lt;span style="color:#f92672"&gt;=&lt;/span&gt; x E,c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;y,d
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;y E;x&lt;span style="color:#f92672"&gt;=&lt;/span&gt;b&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(U)c;y&lt;span style="color:#f92672"&gt;=&lt;/span&gt;a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(U)d;U e &lt;span style="color:#f92672"&gt;=&lt;/span&gt;a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; U)c,f&lt;span style="color:#f92672"&gt;=&lt;/span&gt;b&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(U)d,t;x&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;y;M x&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;y)f &lt;span style="color:#f92672"&gt;+=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1LL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;;t&lt;span style="color:#f92672"&gt;=&lt;/span&gt;x&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;;e&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;t;M e&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;t)f&lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;t&lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x E;f&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;t;R &lt;span style="color:#a6e22e"&gt;AD&lt;/span&gt;(f,e);}U &lt;span style="color:#a6e22e"&gt;J&lt;/span&gt;(U a,U b
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ){U r&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;T i;I i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;;i&lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i&lt;span style="color:#f92672"&gt;--&lt;/span&gt;){r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;(r,r);&lt;span style="color:#a6e22e"&gt;M&lt;/span&gt;(b &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;i)&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;(r
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ,a);}R r;}U &lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;(U a){R &lt;span style="color:#a6e22e"&gt;J&lt;/span&gt;(a,K &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;);}N &lt;span style="color:#a6e22e"&gt;G&lt;/span&gt; (H n,U&lt;span style="color:#f92672"&gt;*&lt;/span&gt;x, U&lt;span style="color:#f92672"&gt;*&lt;/span&gt;y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {T i;I S x[i]&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;(x[i],y[i ]);}N &lt;span style="color:#a6e22e"&gt;g&lt;/span&gt;( H n,U&lt;span style="color:#f92672"&gt;*&lt;/span&gt;x) {T i;I S x[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;(x[i],x[i]);}N &lt;span style="color:#a6e22e"&gt;AA&lt;/span&gt;(){U d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; AC; T k ;I k&lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;F;k&lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;k&lt;span style="color:#f92672"&gt;--&lt;/span&gt;){T m&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;k,c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;m&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,j, r
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;U w&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;I j&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;j&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;c;j&lt;span style="color:#f92672"&gt;++&lt;/span&gt;){I r&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;r&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;n ;r
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;m){T a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;r&lt;span style="color:#f92672"&gt;+&lt;/span&gt;j,b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;a&lt;span style="color:#f92672"&gt;+&lt;/span&gt;c;U u&lt;span style="color:#f92672"&gt;=&lt;/span&gt;x[a] ,v&lt;span style="color:#f92672"&gt;=&lt;/span&gt;x[b] ;x[a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;(u,v);x[b]&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Q&lt;/span&gt;(u,v),w);}w&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;( w,d );}d&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(d,d);}}N &lt;span style="color:#a6e22e"&gt;W&lt;/span&gt;(){T k;I k&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;k&lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt;F;k &lt;span style="color:#f92672"&gt;++&lt;/span&gt; ){T m&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; k, c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;m&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,j,r;U z&lt;span style="color:#f92672"&gt;=&lt;/span&gt;(U)(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;((H)F&lt;span style="color:#f92672"&gt;-&lt;/span&gt;(H)k)), d&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;J&lt;/span&gt;(h,z),w&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;I j&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;j&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;c;j&lt;span style="color:#f92672"&gt;++&lt;/span&gt;){I r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;r&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;n;r&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;m){T a &lt;span style="color:#f92672"&gt;=&lt;/span&gt;r&lt;span style="color:#f92672"&gt;+&lt;/span&gt;j, b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;a&lt;span style="color:#f92672"&gt;+&lt;/span&gt; c;U u&lt;span style="color:#f92672"&gt;=&lt;/span&gt;x[a], v&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt; (w
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;,x[b]);x[a]&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;(u,v);x[b]&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Q&lt;/span&gt;(u,v);}w&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;(w ,d);}}}T &lt;span style="color:#a6e22e"&gt;O&lt;/span&gt;(){T o&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,i, w&lt;span style="color:#f92672"&gt;=&lt;/span&gt;L
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;n;U s&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;J&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;,(K&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;192&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;n&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;);AC&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;J&lt;/span&gt;(s,&lt;span style="color:#ae81ff"&gt;192&lt;/span&gt;) ;h&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;f&lt;/span&gt; (AC );M &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;w &lt;span style="color:#f92672"&gt;+&lt;/span&gt;F
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;61&lt;/span&gt;)R &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;l&lt;span style="color:#f92672"&gt;=&lt;/span&gt;w;D&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;w;p&lt;span style="color:#f92672"&gt;=&lt;/span&gt;w&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;x&lt;span style="color:#f92672"&gt;=&lt;/span&gt;P;B&lt;span style="color:#f92672"&gt;=&lt;/span&gt;P;C&lt;span style="color:#f92672"&gt;=&lt;/span&gt;P; _&lt;span style="color:#f92672"&gt;=&lt;/span&gt; P; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;B&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;C&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;( n);I
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;i&lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt;n;i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;){U t&lt;span style="color:#f92672"&gt;=&lt;/span&gt;(U)L&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(U)i,r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;t&lt;span style="color:#f92672"&gt;%&lt;/span&gt;n,b&lt;span style="color:#f92672"&gt;=&lt;/span&gt;t&lt;span style="color:#f92672"&gt;/&lt;/span&gt;n ;H a;M r
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;E)R &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;&lt;span style="color:#a6e22e"&gt;M&lt;/span&gt;(H)r)b&lt;span style="color:#f92672"&gt;++&lt;/span&gt;;M b E)R &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;a&lt;span style="color:#f92672"&gt;=&lt;/span&gt;b;M i&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;){U c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;_[ i&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;o;M c&lt;span style="color:#f92672"&gt;!=&lt;/span&gt;w&lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;c&lt;span style="color:#f92672"&gt;!=&lt;/span&gt;w&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)R &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;M i&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;n){r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;n&lt;span style="color:#f92672"&gt;-&lt;/span&gt;r;B[i]&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;J&lt;/span&gt;(s,r);C[i]&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;A&lt;/span&gt;(B
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[i],n));}}o&lt;span style="color:#f92672"&gt;=&lt;/span&gt;a;}R &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;}U &lt;span style="color:#a6e22e"&gt;V&lt;/span&gt;(){T i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,j&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;U r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;I;i&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;j&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;n;i&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;_
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[j],j&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)r&lt;span style="color:#f92672"&gt;|=&lt;/span&gt;x[j]&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;i;M r)R r;I r&lt;span style="color:#f92672"&gt;=&lt;/span&gt;j&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;j&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;n;j&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)r&lt;span style="color:#f92672"&gt;|=&lt;/span&gt;x[j];R r;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;N &lt;span style="color:#a6e22e"&gt;X&lt;/span&gt;(H c,T i){&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(c){I;i&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;n;i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;){H y&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;_[i];x[i]&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;c;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;M x[i]&lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt;y)x[ i]&lt;span style="color:#f92672"&gt;-=&lt;/span&gt;y,c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;R;}i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;} }N &lt;span style="color:#a6e22e"&gt;Y&lt;/span&gt;(H c){T i;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(c) {I S{H y&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; _[i] ;x[i ]&lt;span style="color:#f92672"&gt;-=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;c;M x[i]&lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt;y)x[i]&lt;span style="color:#f92672"&gt;+=&lt;/span&gt;y,c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; R ;}}}N
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Z&lt;/span&gt;(U c){T i;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(c){I S{x[ i]&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;AB&lt;/span&gt;(x[i],_[i],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;c);H t&lt;span style="color:#f92672"&gt;=&lt;/span&gt;c;M&lt;span style="color:#f92672"&gt;!&lt;/span&gt;(c E)&lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;t &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;D){M t ) &lt;span style="color:#a6e22e"&gt;X&lt;/span&gt;(t,i&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);R;}}}}N &lt;span style="color:#a6e22e"&gt;q&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{T i;U c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;&lt;span style="color:#a6e22e"&gt;G&lt;/span&gt;(n,x, B);&lt;span style="color:#a6e22e"&gt;AA&lt;/span&gt;(F,x);&lt;span style="color:#a6e22e"&gt;g&lt;/span&gt;(n,x);&lt;span style="color:#a6e22e"&gt;W&lt;/span&gt;(F ,x);&lt;span style="color:#a6e22e"&gt;G&lt;/span&gt;(n,x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;,C);I S x[i]&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AB&lt;/span&gt;(x[i],_[i],&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;c);M c)&lt;span style="color:#a6e22e"&gt;Z&lt;/span&gt;(c);&lt;span style="color:#a6e22e"&gt;Y&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;);}T &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;T w,&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;&lt;span style="color:#f92672"&gt;**&lt;/span&gt; v){T i,k,j;M w&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;) {&lt;span style="color:#a6e22e"&gt;puts&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Usage: p [n]&amp;#34;&lt;/span&gt;);R &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;}L&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;atoi&lt;/span&gt; (v[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] );j&lt;span style="color:#f92672"&gt;=&lt;/span&gt;w&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;atoi&lt;/span&gt;(v[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;])&lt;span style="color:#f92672"&gt;:&lt;/span&gt;L&lt;span style="color:#f92672"&gt;-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; F&lt;span style="color:#f92672"&gt;++&lt;/span&gt; ,n&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;F;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;O&lt;/span&gt; ());I k&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;k
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;k&lt;span style="color:#f92672"&gt;++&lt;/span&gt;){&lt;span style="color:#f92672"&gt;*&lt;/span&gt;x&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;;I i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;i&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;j;i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;q&lt;/span&gt;();}&lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;0x%016&amp;#34;&lt;/span&gt;PRIX64&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;V&lt;/span&gt;());R &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I'm going to explain exactly what it does and how, but first here are
the hints and remarks I provided with the code. Some of the hints assume
you've pre-processed the code into something vaguely legible first.&lt;/p&gt;
&lt;h2 id="hints"&gt;Hints&lt;/h2&gt;
&lt;p&gt;You stare at the source code... Is that a picture of a
&lt;a href="http://en.wikipedia.org/wiki/Marin_Mersenne"&gt;monk&lt;/a&gt;? What does that
strange mathematical writing say? You get a subliminal message... Hunt
for primes? But how?&lt;/p&gt;
&lt;p&gt;You run the program. It comes up with a strange usage message. What
could &lt;code&gt;p&lt;/code&gt; be? You try running the program with a prime number as an
argument.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;./prog 23209&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It returns after a few seconds with the rather cryptic message&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;0x0000000000000000&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What could that mean? Maybe that 2&lt;sup&gt;23209&lt;/sup&gt;-1 (a 6,987 digit number) is
prime after all?&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;OK If you haven't guessed by now, this program proves the primality of
&lt;a href="http://en.wikipedia.org/wiki/Mersenne_prime"&gt;Mersenne primes&lt;/a&gt; of the
form 2&lt;sup&gt;p&lt;/sup&gt;-1. The biggest known primes are of this form because there is
an efficient test for primality - the &lt;a href="http://mathworld.wolfram.com/Lucas-LehmerTest.html"&gt;Lucas Lehmer
test&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you run the program and it produces &lt;code&gt;0x0000000000000000&lt;/code&gt; (0 in hex)
as an answer then you've found a prime of the form 2&lt;sup&gt;p&lt;/sup&gt;-1. If it
produces anything else then 2&lt;sup&gt;p&lt;/sup&gt;-1 isn't prime. The printed result is
the bottom 64 bits of the last iteration of the Lucas Lehmer test.&lt;/p&gt;
&lt;p&gt;Have a look at the source code and see if you can work out how it
implements the Lucas Lehmer test...&lt;/p&gt;
&lt;p&gt;Your first clue is to work out what the magic number &lt;code&gt;-(U)(H)-1&lt;/code&gt; is. (My
favourite bit of obfuscation!)&lt;/p&gt;
&lt;p&gt;Got it? It is a prime just less than 2&lt;sup&gt;64&lt;/sup&gt;, &lt;code&gt;0xFFFFFFFF00000001&lt;/code&gt; =
2&lt;sup&gt;64&lt;/sup&gt; - 2&lt;sup&gt;32&lt;/sup&gt; + 1 (p from now on), with some rather special properties.&lt;/p&gt;
&lt;p&gt;The most important of which is that arithmetic modulo p can all be done
without using divisions or modulo operations (which are really slow).
See if you can spot the add, subtract and multiplication routines. There
are also reciprocal and to the power operations in there somewhere.&lt;/p&gt;
&lt;p&gt;The next important property is that p-1 has the following factors&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2^32 * 3 * 5 * 17 * 257 * 65537
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All those factors of 2 suggest that we can do a &lt;a href="http://mathworld.wolfram.com/FastFourierTransform.html"&gt;Fast Fourier
Transform&lt;/a&gt; over
the &lt;a href="http://mathworld.wolfram.com/FiniteField.html"&gt;Galois Field&lt;/a&gt; GF(p)
which is arithmetic modulo p. See if you can spot the FFT code!&lt;/p&gt;
&lt;p&gt;To make a truly efficient Mersenne primality prover it is necessary to
implement the
&lt;a href="http://en.wikipedia.org/wiki/Irrational_base_discrete_weighted_transform"&gt;IBDWT&lt;/a&gt;
a variant of the FFT using an irrational base. This halves the size of
the FFT array by combining the modulo and multiply steps from the Lucas
Lehmer test into one. You might wonder how you can use an irrational
base in a discrete field where every element is an integer, but as it
happens the p chosen has n-th roots of 2 where n is up to 26, which
means that an IBDWT can be defined for FFT sizes up to 2&lt;sup&gt;26&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;You'll find the code to generate the roots of 1 and 2 necessary for the
IBDWT if you search for 7 in the code. 7 is a primitive root of GF(p) so
all follows from that!&lt;/p&gt;
&lt;p&gt;This all integer IBDWT isn't susceptible to the round off errors that
plague the floating point implementation, but does suffer in the speed
stakes from the fact that modern CPUs have much faster floating point
units than integer units.&lt;/p&gt;
&lt;p&gt;For example to check if 2&lt;sup&gt;18000000&lt;/sup&gt;-1 is prime (a 5,418,539 digit
number) &lt;a href="http://www.mersenne.org/freesoft/"&gt;Prime95&lt;/a&gt; (the current speed
demon) uses a 2&lt;sup&gt;20&lt;/sup&gt; FFT size and each iteration takes it about 25ms. On
similar hardware it this program takes about 1.2s also using an FFT size
of 2&lt;sup&gt;20&lt;/sup&gt;! Prime95 is written in optimised assembler to use SSE3 whereas
this program was squeezed into 2k of portable C with a completely
unoptimised FFT!&lt;/p&gt;
&lt;p&gt;This program can do an FFT of up to 2&lt;sup&gt;26&lt;/sup&gt; entries. Each entry can have
up to 18 bits in (as &lt;code&gt;2*18+26 &amp;lt;= 63&lt;/code&gt;), which means that the biggest
exponent that it can test for primality is 18*2&lt;sup&gt;26&lt;/sup&gt;-1 = 1,207,959,551.
This would be number of 363 million decimal digits so could be used to
find a 100 million digit prime and scoop the &lt;a href="https://www.eff.org/awards/coop"&gt;EFF $150,000
prize&lt;/a&gt;! It would take rather a long
time though...&lt;/p&gt;
&lt;p&gt;The second argument to the program allows the number of iterations to be
put in, and using this it has been validated against the Prime95 test
suite. There is a unit test for the program but I thought including it
was probably against the spirit of the contest!&lt;/p&gt;
&lt;p&gt;Speed of the FFT could be improved greatly, but unfortunately there
wasn't space in the margin to do so ;-)&lt;/p&gt;
&lt;h1 id="remarks-about-the-code"&gt;Remarks about the Code&lt;/h1&gt;
&lt;p&gt;This should compile on any compiler which supports &lt;code&gt;inttypes.h&lt;/code&gt; from the
C99 standard (eg gcc).&lt;/p&gt;
&lt;p&gt;It runs a lot quicker when compiled as a 64 bit binary!&lt;/p&gt;
&lt;p&gt;I have successfully compiled and run this program without changes or
compiler warnings for:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;64 bit Ubuntu Linux 11.10&lt;/li&gt;
&lt;li&gt;32 bit Debian Linux (Lenny)&lt;/li&gt;
&lt;li&gt;Windows using &lt;a href="http://www.mingw.org/"&gt;MINGW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OS X 10.7 using Apple's gcc based compiler&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you don't have a compiler which supports &lt;code&gt;inttypes.h&lt;/code&gt; from C99
(hello it is 2012 Microsoft!) then you'll need to go platform specific:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;comment out the &lt;code&gt;#include &amp;lt;inttypes.h&amp;gt;&lt;/code&gt; line&lt;/li&gt;
&lt;li&gt;change the &lt;code&gt;#define&lt;/code&gt; for &lt;code&gt;uint32_t&lt;/code&gt; to be an unsigned 32 bit type
&lt;code&gt;unsigned int&lt;/code&gt; or &lt;code&gt;unsigned __int32&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;change the &lt;code&gt;#define&lt;/code&gt; for &lt;code&gt;uint64_t&lt;/code&gt; to be an unsigned 64 bit type
&lt;code&gt;unsigned long long&lt;/code&gt; or &lt;code&gt;unsigned __int64&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;#define PRIX64 &amp;quot;llX&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;lX&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;I64X&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h1 id="how-it-was-written"&gt;How it was written&lt;/h1&gt;
&lt;p&gt;I wrote most of this code some time ago as a view to publishing a full
description of how my &lt;a href="https://ncw.github.io/www/nick/armprime/"&gt;ARMprime&lt;/a&gt; code works in easy to
understand C rather than a twisty turny mess of ARM assembler macros.&lt;/p&gt;
&lt;p&gt;However I never got round to finishing it, so I used the IOCCC as a spur
to get me to finish it properly!&lt;/p&gt;
&lt;p&gt;I've open-sourced the code and the build chain at
&lt;a href="https://github.com/ncw/ioccc2012"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As you can imagine it isn't possible to develop the code in the form
above from scratch! I created an unobfuscated version
&lt;a href="https://github.com/ncw/ioccc2012/blob/master/mersenne.c"&gt;mersenne.c&lt;/a&gt;
first and then wrote two programs, one which compresses the code (it
uses a manual version of LZ77 compression with &lt;code&gt;#define&lt;/code&gt; statements) and
another which makes it into the pretty picture.&lt;/p&gt;
&lt;p&gt;This means that I can change the code and just type make to create the
final pretty code for the entry, and to run the unit tests with.&lt;/p&gt;
&lt;p&gt;The first challenge was cutting the code down to size. It needed to be
less than 2k of non-whitespace characters and less than 4k total. I went
through it getting rid of all extraneous functions, compacting
definitions, removing optimisations, obfuscating and it was still far
too big.&lt;/p&gt;
&lt;p&gt;With the help of
&lt;a href="https://github.com/ncw/ioccc2012/blob/master/crush.py"&gt;crush.py&lt;/a&gt; and
after many hours of work I managed to get it small enough. I then wrote
&lt;a href="https://github.com/ncw/ioccc2012/blob/master/check.py"&gt;check.py&lt;/a&gt; to see
whether the code was within the competition rules and
&lt;a href="https://github.com/ncw/ioccc2012/blob/master/unit_test.py"&gt;unit_test.py&lt;/a&gt;
to validate the code against Prime95's test suite.&lt;/p&gt;
&lt;p&gt;Finally I wrote
&lt;a href="https://github.com/ncw/ioccc2012/blob/master/artify.py"&gt;artify.py&lt;/a&gt;
which reads the crushed source code and uses it to paint the image. It
treats each character (or sometimes a group of characters so the C
remains valid) as a pixel and paints the image with code!&lt;/p&gt;
&lt;p&gt;Note that none of the python programs are particularly tidy, but that
python is a really good language for doing this in - I'd hate to be
doing it in C!&lt;/p&gt;
&lt;h1 id="how-it-works"&gt;How it works&lt;/h1&gt;
&lt;p&gt;Now I've introduced the unobfuscated version, I can show how each part
of the code works.&lt;/p&gt;
&lt;p&gt;Firstly all good obfuscated programs have lots of global variables to
shorten the code down:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;u64 MOD_P &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;(u64)(u32)&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#75715e"&gt;/* 0xFFFFFFFF00000001 - the magic number */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;digit_weight, &lt;span style="color:#75715e"&gt;/* Array of weights for IBDWT */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;digit_unweight, &lt;span style="color:#75715e"&gt;/* Inverse of the above */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;x, &lt;span style="color:#75715e"&gt;/* pointer to array of n 64 bit integers - the current number */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MOD_W, &lt;span style="color:#75715e"&gt;/* The root of 2 for the fft so that 2**MOD_W == 1 mod p */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MOD_INVW; &lt;span style="color:#75715e"&gt;/* The inverse of the above so that MOD_W * MOD_INVW == 1 mod p */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; exponent, &lt;span style="color:#75715e"&gt;/* The mersenne exponent - we are testing 2^exponent -1 is prime or not */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n, &lt;span style="color:#75715e"&gt;/* The number of 64 bit numbers in the FFT */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; log_n, &lt;span style="color:#75715e"&gt;/* n = 2^log_n */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; digit_width0, &lt;span style="color:#75715e"&gt;/* Digit width for the IBDWT */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; digit_width1,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; digit_width_0_max,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;digit_widths; &lt;span style="color:#75715e"&gt;/* Array of number of bits in each element of the FFT */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the top down there is the main loop which contains the Lucas Lehmer
algorithm:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; w, &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt; v)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i,k,j;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (w &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;puts&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Usage:@p@[n]&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; exponent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;atoi&lt;/span&gt;(v[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j &lt;span style="color:#f92672"&gt;=&lt;/span&gt; w &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;atoi&lt;/span&gt;(v[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]) &lt;span style="color:#f92672"&gt;:&lt;/span&gt; exponent &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;; &lt;span style="color:#75715e"&gt;/* iterations */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* initialise, finding correct FFT size */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; log_n&lt;span style="color:#f92672"&gt;++&lt;/span&gt;, n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; log_n;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;mersenne_initialise&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (k &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; k &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; k&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; j; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mersenne_mul&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;0x%016&amp;#34;&lt;/span&gt; PRIX64 &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;mersenne_residue&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It reads the exponent and optional number of iterations from the command
line, then initialises the program, starting with a small FFT size &lt;code&gt;n&lt;/code&gt;
and increasing until it finds one which fits.&lt;/p&gt;
&lt;p&gt;It then does the Lucas Lehmer test setting the initial value to 4,
iterating it for exponent times and printing the residue.&lt;/p&gt;
&lt;p&gt;The core of the Lucas Lehmer test (and the
&lt;a href="http://en.wikipedia.org/wiki/Irrational_base_discrete_weighted_transform"&gt;IBDWT&lt;/a&gt;)
is the &lt;code&gt;mersenne_mul&lt;/code&gt; function which squares the current number and
subtracts 2, returning it modulo 2&lt;sup&gt;p&lt;/sup&gt; - 1 :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mersenne_mul&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u64 c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* weight the input */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mod_vector_mul&lt;/span&gt;(n, x, digit_weight);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* transform */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fft_fastish&lt;/span&gt;(log_n, x);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* point multiply */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mod_sqr_vector&lt;/span&gt;(n, x);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* untransform */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;invFft_fastish&lt;/span&gt;(log_n, x);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* unweight and normalise the output */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mod_vector_mul&lt;/span&gt;(n, x, digit_unweight);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* carry propagation */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; n; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x[i] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_adc&lt;/span&gt;(x[i], digit_widths[i], &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;c);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (c)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mersenne_add64&lt;/span&gt;(c);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* subtract 2 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mersenne_sub32&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This the FFT, point multiply and inverse FFT perform a convolution. This
does the bulk of the work of the multiplication. The weight and unweight
and the start and end is the IBDWT which ensures that the result is
modulo 2&lt;sup&gt;p&lt;/sup&gt; - 1. The carries are propagated and 2 is subtracted from
the end.&lt;/p&gt;
&lt;p&gt;The FFT is a completely standard FFT with bit reversed output, the only
unusual thing being that all the operations are mod p rather than with
complex numbers. If you compare the code for the FFT with a standard
implementation you will see it is very similar:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fft_fastish&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u64 d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; MOD_W;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; k;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (k &lt;span style="color:#f92672"&gt;=&lt;/span&gt; log_n; k &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; k&lt;span style="color:#f92672"&gt;--&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; m &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; k,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; m &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; j,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u64 w &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (j &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; j &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; c; j&lt;span style="color:#f92672"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (r &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; r &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; n; r &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; m)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; r &lt;span style="color:#f92672"&gt;+&lt;/span&gt; j,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; c;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u64 u &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x[a],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x[b];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x[a] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_add&lt;/span&gt;(u, v);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x[b] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_mul&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;mod_sub&lt;/span&gt;(u, v), w);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; w &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_mul&lt;/span&gt;(w, d);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_mul&lt;/span&gt;(d, d);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;MOD_W&lt;/code&gt; is the root of unity the FFT is built on. It happens to be an
integer in GF(p) such that &lt;code&gt;MOD_W&lt;/code&gt;&lt;sup&gt;n&lt;/sup&gt; == 1 mod p. You can see the FFT
calculating the twiddles (&lt;code&gt;w&lt;/code&gt;). Precalculating them would be better
obviously but not in 2k of code! The inner loop shows the butterfly.&lt;/p&gt;
&lt;p&gt;Now for the fundamental operations over GF(p). First thing to note is
that in the code p = &lt;code&gt;MOD_P&lt;/code&gt; = 2&lt;sup&gt;64&lt;/sup&gt; - 2&lt;sup&gt;32&lt;/sup&gt; + 1. &lt;code&gt;MOD_P&lt;/code&gt; was chosen so
that it has quite a few special properties, one of them being that it is
possible to do modulo p operations without doing divisions (which are
really slow!).&lt;/p&gt;
&lt;p&gt;The easiest operation to define is subtraction:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;u64 &lt;span style="color:#a6e22e"&gt;mod_sub&lt;/span&gt;(u64 x, u64 y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u64 r &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;-&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* if borrow generated - hopefully the compiler will optimise this! */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (x &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; MOD_P; &lt;span style="color:#75715e"&gt;/* Add back p if borrow */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; r;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The C code was designed so that the if statement should be optimised
into a jump on carry flag if the compiler is doing its job properly.
Addition can then be defined as subtracting a negative number:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;u64 &lt;span style="color:#a6e22e"&gt;mod_add&lt;/span&gt;(u64 x, u64 y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; MOD_P &lt;span style="color:#f92672"&gt;-&lt;/span&gt; x; &lt;span style="color:#75715e"&gt;/* do addition by negating y then subtracting */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u64 r &lt;span style="color:#f92672"&gt;=&lt;/span&gt; y &lt;span style="color:#f92672"&gt;-&lt;/span&gt; x; &lt;span style="color:#75715e"&gt;/* y - (-x) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* if borrow generated - hopefully the compiler will optimise this! */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (y &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; x)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; MOD_P; &lt;span style="color:#75715e"&gt;/* Add back p if borrow */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; r;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To do multiplication, first it is necessary to work out how to do reduce
a 128 bit number mod p. We use these facts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2&lt;sup&gt;64&lt;/sup&gt; == 2&lt;sup&gt;32&lt;/sup&gt; -1 mod p&lt;/li&gt;
&lt;li&gt;2&lt;sup&gt;96&lt;/sup&gt; == -1 mod p&lt;/li&gt;
&lt;li&gt;2&lt;sup&gt;128&lt;/sup&gt; == -2&lt;sup&gt;32&lt;/sup&gt; mod p&lt;/li&gt;
&lt;li&gt;2&lt;sup&gt;192&lt;/sup&gt; == 1 mod p&lt;/li&gt;
&lt;li&gt;2&lt;sup&gt;n&lt;/sup&gt; * 2&lt;sup&gt;(192-n)&lt;/sup&gt; = 1 mod p&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thus to reduce a 128 bit number mod p (split into 32 bit chunks
x3,x2,x1,x0):&lt;/p&gt;
&lt;p&gt;x3 * 2&lt;sup&gt;96&lt;/sup&gt; + x2 * 2&lt;sup&gt;64&lt;/sup&gt; + x1 * 2&lt;sup&gt;32&lt;/sup&gt; + x0 mod p &lt;br&gt;
= x2 * 2&lt;sup&gt;64&lt;/sup&gt; + x1*2&lt;sup&gt;32&lt;/sup&gt; + x0-x3) [using 2&lt;sup&gt;96&lt;/sup&gt; mod p = -1] &lt;br&gt;
= (x1+x2) * 2&lt;sup&gt;32&lt;/sup&gt; + x0 - x3 - x2 [using 2&lt;sup&gt;64&lt;/sup&gt; mod p = 2&lt;sup&gt;32&lt;/sup&gt; -1]&lt;/p&gt;
&lt;p&gt;This is explained in more detail in my &lt;a href="https://ncw.github.io/www/nick/armprime/"&gt;ARMprime&lt;/a&gt;
pages. This division free code then looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;u64 &lt;span style="color:#a6e22e"&gt;mod_reduce&lt;/span&gt;(u64 b, u64 a)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u32 d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; b &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (a &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; MOD_P) &lt;span style="color:#75715e"&gt;/* (x1, x0) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a &lt;span style="color:#f92672"&gt;-=&lt;/span&gt; MOD_P;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_sub&lt;/span&gt;(a, c);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_sub&lt;/span&gt;(a, d);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_add&lt;/span&gt;(a, ((u64)c)&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Given &lt;code&gt;mod_reduce&lt;/code&gt;, multiplication is relatively straight forward:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;u64 &lt;span style="color:#a6e22e"&gt;mod_mul&lt;/span&gt;(u64 x, u64 y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u32 a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; y,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; y &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* first synthesise the product using 32*32 -&amp;gt; 64 bit multiplies */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; b &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (u64)c;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (u64)d;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; u64 e &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (u64)c,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; f &lt;span style="color:#f92672"&gt;=&lt;/span&gt; b &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (u64)d,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; y; &lt;span style="color:#75715e"&gt;/* b*c + a*d */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* carry? */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (x &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; f &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1LL&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;; &lt;span style="color:#75715e"&gt;/* carry into upper 32 bits - can&amp;#39;t overflow */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; t; &lt;span style="color:#75715e"&gt;/* a*c + LSW(b*c + a*d) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* carry? */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (e &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; t)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; f &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;span style="color:#75715e"&gt;/* carry into upper 64 bits - can&amp;#39;t overflow*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; f &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; t; &lt;span style="color:#75715e"&gt;/* b*d + MSW(b*c + a*d) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* can&amp;#39;t overflow */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* now reduce: (b*d + MSW(b*c + a*d), a*c + LSW(b*c + a*d)) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mod_reduce&lt;/span&gt;(f, e);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The definitions for the other arithmetic operations are straight forward
now. Power is just repeated multiplication and squaring. Inverse is to
the power of -1.&lt;/p&gt;
&lt;p&gt;All those things come together in the &lt;code&gt;mersenne_mul&lt;/code&gt; function above!&lt;/p&gt;
&lt;p&gt;If you want to look at the complete (mostly) unobfuscated code then take
look through
&lt;a href="https://github.com/ncw/ioccc2012/blob/master/mersenne.c"&gt;mersenne.c&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The IOCCC was a fun challenge and it got me to finally complete my C
conversion of a lot of really difficult ARM assembly code. Hopefully
I'll find the time to demonstrate some more optimised FFTs and an FFT
with a factor of 3 in too.&lt;/p&gt;
&lt;p&gt;Getting the code small enough was really, really difficult, but helped
immensely by Python. It started off life as pretty obscure so that
process made it more so! I'm afraid even as explained above it probably
isn't accessible to very many people - my apologies for that.&lt;/p&gt;
&lt;p&gt;Happy Prime Hunting!&lt;/p&gt;</description></item><item><title>How I Solved the GCHQ challenge</title><link>https://ncw.github.io/www/articles/gchq-challenge/</link><pubDate>Sun, 04 Dec 2011 20:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/gchq-challenge/</guid><description>&lt;p&gt;This is an unsanitised account of how I solved the GCHQ challenge at
&lt;a href="http://www.canyoucrackit.co.uk/"&gt;http://www.canyoucrackit.co.uk/&lt;/a&gt;. &lt;a href="http://www.bbc.co.uk/news/technology-15968878"&gt;According to the
BBC&lt;/a&gt; the competition
began in secret on the 3rd of November 2011 and will continue until the
12th of December. I was going to hold back this publication until the
contest ended but &lt;a href="http://news.slashdot.org/story/11/12/04/1725253/gchq-challenge-solution-explained"&gt;a
solution&lt;/a&gt;
has just made it to the front page of slashdot so I think the jig is up!&lt;/p&gt;
&lt;p&gt;This writeup includes the wrong turnings I took and the bad assumptions
I made along the way so any reader can see the kind of thought processes
necessary. I very deliberately did no searching on the Internet about
the puzzle so all the work below (and the mistakes) are mine alone!&lt;/p&gt;
&lt;p&gt;The programs linked to in the article are the final versions, I didn't
keep the intermediate versions which I talk about in the text, so
you'll have to imagine what they looked like.&lt;/p&gt;
&lt;div class="card float-right" style="max-width: 18rem;"&gt;
&lt;div class="card-header" style="padding: 5px 10px;"&gt;
Warning
&lt;/div&gt;
&lt;div class="card-body"&gt;
This article contains spoilers on how to do the challenge - don't read
any further if you want to solve it yourself!
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id="stage-1"&gt;Stage 1&lt;/h1&gt;
&lt;p&gt;The challenge opens showing a single image with a load of hex digits in
and a form to submit your answer. The image looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="cyber.png" alt="GCHQ cyber challenge"&gt;&lt;/p&gt;
&lt;p&gt;The first thing I did was to decode the hex data. Using a python program
of course! I played around with trying to get it to display an image. It
is obviously low entropy but what is it? Not an image anyway.&lt;/p&gt;
&lt;p&gt;I used &lt;a href="cyber.py"&gt;cyber.py&lt;/a&gt; to save it to a
binary file and ran the unix &amp;quot;file&amp;quot; utility on it which told me it was
x86 code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ file cyber.bin
cyber.bin: DOS executable (COM)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Interesting. A disassembly was required
&lt;a href="cyber.disassembly.asm"&gt;cyber.disassembly.asm&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;x86dis -r 0 160 -s intel &amp;lt; cyber.bin &amp;gt; cyber.disassembly.asm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code appeared to be linux flavour, exiting politely with the correct
&lt;code&gt;int 0x80&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;The obvious next step is to run the code. It is bare code which you
can't just run on any modern OS. I could have added headers to it but I
decided to write &lt;a href="cyber.c"&gt;cyber.c&lt;/a&gt; to load it
into memory instead. I used &lt;code&gt;mmap&lt;/code&gt; to map a padded version of the code
so I could get the code and the stack under my control and examine it
after the code had exited:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gcc -g -m32 -Wall -static -o cyber cyber.c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running the code, it seemed to be early terminating - needing 0x42424242
or &amp;quot;BBBB&amp;quot; on the end to continue according to this bit of code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0000004A 58 pop eax
0000004B 3D 42 42 42 42 cmp eax, 0x42424242
00000050 75 3B jnz 0x0000008D ; exit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I tried padding with &amp;quot;BBBB&amp;quot; and it core dumped this time. After
studying the disassembly some more and experimenting I noted that it
needed &amp;quot;BBBB&amp;quot; &lt;strong&gt;and&lt;/strong&gt; a 4 byte length. Running that it appears to
decrypt something on the stack this time, so I'm getting somewhere.&lt;/p&gt;
&lt;p&gt;But what to decrypt? I needed a string starting with &amp;quot;BBBB&amp;quot;. I
recursively downloaded the entire website and grepped it for &amp;quot;BBBB&amp;quot;
without success. However on really close examination of a hex dump of
cyber.png I discovered this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;00000050: 1233 7e39 c170 0000 005d 6954 5874 436f .3~9.p...]iTXtCo
00000060: 6d6d 656e 7400 0000 0000 516b 4a43 516a mment.....QkJCQj
00000070: 4941 4141 4352 3250 4674 6343 4136 7132 IAAACR2PFtcCA6q2
00000080: 6561 4338 5352 2b38 646d 442f 7a4e 7a4c eaC8SR+8dmD/zNzL
00000090: 5143 2b74 6433 7446 5134 7178 384f 3434 QC+td3tFQ4qx8O44
000000a0: 3754 4465 755a 7735 502b 3053 7362 4563 7TDeuZw5P+0SsbEc
000000b0: 5952 0a37 386a 4b4c 773d 3d32 cabe f100 YR.78jKLw==2....
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That string &amp;quot;QkJCQj...78jKLw==&amp;quot; with upper and lower case letters,
'+' and '/' and the trailing '==' screams &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;base64
encoding&lt;/a&gt; to me. I decoded it in
python and it decodes to &lt;code&gt;BBBB2\x00\x00\x00\x91&lt;/code&gt;... -hooray a string
starting with &amp;quot;BBBB&amp;quot; and a sensible looking length! I then modified
&lt;a href="cyber.py"&gt;cyber.py&lt;/a&gt; to add that on the end of
the code and ran the &lt;a href="cyber.c"&gt;cyber.c&lt;/a&gt; binary.
After it had ran I examined the stack in the &lt;code&gt;cyber.bin.padded&lt;/code&gt; file
originally written by &lt;code&gt;cyber.py&lt;/code&gt;. I saw this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;00002c0: 00 00 00 00 00 00 00 00 00 00 47 45 54 20 2f 31 ..........GET /1
00002d0: 35 62 34 33 36 64 65 31 66 39 31 30 37 66 33 37 5b436de1f9107f37
00002e0: 37 38 61 61 64 35 32 35 65 35 64 30 62 32 30 2e 78aad525e5d0b20.
00002f0: 6a 73 20 48 54 54 50 2f de e6 fb 2f ef ae 5d aa js HTTP/.../..].
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which looks very like an HTTP transaction, ie a coded instruction to
fetch a file, so I did:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ wget http://www.canyoucrackit.co.uk/15b436de1f9107f3778aad525e5d0b20.js
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="stage-2"&gt;Stage 2&lt;/h1&gt;
&lt;p&gt;The downloaded file
&lt;a href="15b436de1f9107f3778aad525e5d0b20.js"&gt;15b436de1f9107f3778aad525e5d0b20.js&lt;/a&gt;
is a description of a VM with an initial state, but no code to implement
the VM. It has a very realistic and amusing initial commment! It also
says &amp;quot;stage 2 of 3&amp;quot; which is the first indication how long this
challenge is going to be.&lt;/p&gt;
&lt;p&gt;Otherwise it seems a reasonably straightforward job to implement the VM
and I got cracking on &lt;a href="vm.py"&gt;vm.py&lt;/a&gt; after
reading that. Note that it has 8 bytes of 'firmware' which don't seem
to fit in anywhere which is a bit puzzling.&lt;/p&gt;
&lt;p&gt;Wasted a lot of time trying to get the VM to work. Tried poking the
firmware in various imaginitive places. Found a few bugs then finally
re-read the doc again - Ah-ha it is 16 byte segment size, not a 16 bit
register... Duh!&lt;/p&gt;
&lt;p&gt;Fixed that and it runs much better now actually decrypting stuff and
halts properly.&lt;/p&gt;
&lt;p&gt;Found this in the memory in &lt;code&gt;final.core&lt;/code&gt; after
&lt;a href="vm.py"&gt;vm.py&lt;/a&gt; had run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;00001c0: 47 45 54 20 2f 64 61 37 35 33 37 30 66 65 31 35 GET /da75370fe15
00001d0: 63 34 31 34 38 62 64 34 63 65 65 63 38 36 31 66 c4148bd4ceec861f
00001e0: 62 64 61 61 35 2e 65 78 65 20 48 54 54 50 2f 31 bdaa5.exe HTTP/1
00001f0: 2e 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .0..............
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That seems like an instruction to fetch something from the web site
again:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ wget http://www.canyoucrackit.co.uk/da75370fe15c4148bd4ceec861fbdaa5.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Haven't used the firmware - wonder where that fits in...&lt;/p&gt;
&lt;h1 id="stage-3"&gt;Stage 3&lt;/h1&gt;
&lt;p&gt;I looked in
&lt;a href="da75370fe15c4148bd4ceec861fbdaa5.exe"&gt;da75370fe15c4148bd4ceec861fbdaa5.exe&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;and found it to be a windows x86 executable. It seems to be using the
cygcrypt dll from cygwin and the &lt;code&gt;crypt()&lt;/code&gt; function. It has a string in
it which looks exactly like a DES password crypt &amp;quot;hqDTK7b8K2rvw&amp;quot;. I
then set &lt;a href="http://www.openwall.com/john/"&gt;John the Ripper&lt;/a&gt; and
&lt;a href="http://packages.debian.org/squeeze/crack"&gt;crack&lt;/a&gt; off on it for good
measure to find the encrypted password.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;John the Ripper found the password &lt;code&gt;cyberwin&lt;/code&gt; in 2 hours. The easy one
was my test to make sure it was working:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Loaded 2 password hashes with 2 different salts (Traditional DES [128/128 BS SSE2-16])
easy (trivial)
cyberwin (test)
guesses: 2 time: 0:02:01:42 (3) c/s: 1537K trying: cufqnm5! - cyberwen
Use the &amp;quot;--show&amp;quot; option to display all of the cracked passwords reliably
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And double checking with python:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; crypt(&amp;quot;cyberwin&amp;quot;, &amp;quot;hq&amp;quot;) == &amp;quot;hqDTK7b8K2rvw&amp;quot;
True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Meanwhile I tried running the exe on windows but it doesn't run without
that dll.&lt;/p&gt;
&lt;p&gt;After installing cygwin with the &amp;quot;crypt&amp;quot; package which has the correct
dll in, I copied &lt;code&gt;cygcrypt-0.dll&lt;/code&gt; and &lt;code&gt;cygwin1.dll&lt;/code&gt; into my working
directory. The exe now runs and gives:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;da75370fe15c4148bd4ceec861fbdaa5.exe
keygen.exe
usage: keygen.exe hostname
&amp;gt;da75370fe15c4148bd4ceec861fbdaa5.exe localhost
keygen.exe
error: license.txt not found
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then tried it with &amp;quot;cyberwin&amp;quot; in license.txt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;da75370fe15c4148bd4ceec861fbdaa5.exe localhost
keygen.exe
error: license.txt invalid
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hmm, I was expecting that to work.&lt;/p&gt;
&lt;p&gt;Looking through the
&lt;a href="keygen.edit.asm"&gt;keygen.edit.asm&lt;/a&gt; (my annotated
version) I discovered that the password should be prefixed with
&amp;quot;gchq&amp;quot;. The first hint as to who set this puzzle! :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cmp [ebp+var_38], 71686367h ; gchq
jnz short invalid_license
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Putting &amp;quot;gchqcyberwin&amp;quot; into the &lt;code&gt;license.txt&lt;/code&gt; and running the program
goes better this time. It fetches a page this time, but it is a 404 not
found. Note that this isn't the normal 404 page because the exe uses
HTTP/1.0 rather than HTTP/1.1:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;da75370fe15c4148bd4ceec861fbdaa5.exe www.canyoucrackit.co.uk
keygen.exe
loading stage1 license key(s)...
loading stage2 license key(s)...
request:
GET /hqDTK7b8K2rvw/0/0/0/key.txt HTTP/1.0
response:
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 03 Dec 2011 09:29:29 GMT
Connection: close
Content-Length: 315
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot;&amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;
&amp;lt;HTML&amp;gt;&amp;lt;HEAD&amp;gt;&amp;lt;TITLE&amp;gt;Not Found&amp;lt;/TITLE&amp;gt;
&amp;lt;META HTTP-EQUIV=&amp;quot;Content-Type&amp;quot; Content=&amp;quot;text/html; charset=us-ascii&amp;quot;&amp;gt;&amp;lt;/HEAD&amp;gt;
&amp;lt;BODY&amp;gt;&amp;lt;h2&amp;gt;Not Found&amp;lt;/h2&amp;gt;
&amp;lt;hr&amp;gt;&amp;lt;p&amp;gt;HTTP Error 404. The requested resource is not found.&amp;lt;/p&amp;gt;
&amp;lt;/BODY&amp;gt;&amp;lt;/HTML&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Trying the above in the web browser gives the normal 404 message. Trying
with telnet see that it needs HTTP/1.0. HTTP/1.1 with host header gives
normal page. Trying &amp;quot;GET / HTTP/1.0&amp;quot; gives the same message so
probably a red herring to do with the server (or not see later!).&lt;/p&gt;
&lt;p&gt;The fact that the page isn't found means that there is something
missing. But what? The code is executing the equivalent of this to make
the GET string to fetch the page:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sprintf(buffer, &amp;quot;GET /%s/%x/%x/%x/key.txt HTTP/1.0\r\n\r\n&amp;quot;, crypted_string, key1, key2, key2);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However key1, key2 and key3 are all 0 which doesn't look right. I tried
some things for those missing %x parameters:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; t = &amp;quot;gchqcyberwin&amp;quot;
&amp;gt;&amp;gt;&amp;gt; from struct import *
&amp;gt;&amp;gt;&amp;gt; [ &amp;quot;%x&amp;quot; %x for x in unpack(&amp;quot;&amp;gt;iii&amp;quot;, t) ]
['67636871', '63796265', '7277696e']
&amp;gt;&amp;gt;&amp;gt; [ &amp;quot;%x&amp;quot; %x for x in unpack(&amp;quot;&amp;lt;iii&amp;quot;, t) ]
['71686367', '65627963', '6e697772']
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Try:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget http://www.canyoucrackit.co.uk/hqDTK7b8K2rvw/71686367/65627963/6e697772/key.txt
wget http://www.canyoucrackit.co.uk/hqDTK7b8K2rvw/67636871/63796265/7277696e/key.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But no luck.&lt;/p&gt;
&lt;p&gt;More study of the &lt;a href="keygen.edit.asm"&gt;keygen.edit.asm&lt;/a&gt;
disassembly reveals that key1, key2, key3 come from the end of the
&lt;code&gt;license.txt&lt;/code&gt; file after &amp;quot;gchqcyberwin&amp;quot;. So that makes 24 bytes of
secrets read from the licence file which is the size of the buffer the
code allocates.&lt;/p&gt;
&lt;p&gt;Ah-Ha! The clue is in the &amp;quot;loading stageX license key(s)...&amp;quot;
messages.&lt;/p&gt;
&lt;p&gt;This bit of assembler code gives it away (annotations by me):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;loc_4011A5: ; &amp;quot;loading stage1 license key(s)...\n&amp;quot;
mov [esp+78h+var_78], offset aLoadingStage1L
call printf
mov eax, [ebp+var_2C] ; copy 4 bytes of the licence file
mov [ebp+var_48], eax
mov [esp+78h+var_78], offset aLoadingStage2L ; &amp;quot;loading stage2 license key(s)...\n\n&amp;quot;
call printf
mov eax, [ebp+var_28] ; ...and another 4 bytes
mov [ebp+var_44], eax
mov eax, [ebp+var_24] ; ..and another 4 bytes
mov [ebp+var_40], eax
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It prints &amp;quot;loading stage1 license keys(s)...&amp;quot; loads 4 bytes, then
&amp;quot;loading stage2 license key(s)...&amp;quot; and loads 8 bytes. Stage 1 is the
first stage of the puzzle - need 4 bytes from this - how about the
unused 4 bytes at the start of the code that is jumped over &amp;quot;af c2 bf
a3&amp;quot;. Stage2 is the second stage from which we need 8 bytes - the
mysteriously unused firmware seems appropriate.&lt;/p&gt;
&lt;p&gt;I wrote &lt;a href="keyfetch.py"&gt;keyfetch.py&lt;/a&gt; to fiddle
with the endianess and after a bit of trial and error it worked:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GET 'http://www.canyoucrackit.co.uk/hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt'
Pr0t3ct!on
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fetched using &lt;code&gt;HTTP/1.1&lt;/code&gt; and the &lt;code&gt;GET&lt;/code&gt; program. Which looks like it
could be the password! But it doesn't work :-(&lt;/p&gt;
&lt;p&gt;The headers showed nothing interesting. I then tried using &lt;code&gt;keygen.exe&lt;/code&gt;
with a corrected license file - it didn't work as I expected as the
webserver doesn't support HTTP/1.0 (or maybe I did something wrong).&lt;/p&gt;
&lt;p&gt;However trying it by hand using telnet and &lt;code&gt;HTTP/1.0&lt;/code&gt; does do something
different:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ telnet www.canyoucrackit.co.uk 80
Trying 31.222.164.161...
Connected to www.canyoucrackit.co.uk.
Escape character is '^]'.
GET http://www.canyoucrackit.co.uk/hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt HTTP/1.0
HTTP/1.1 200 OK
Content-Type: text/plain
Last-Modified: Wed, 26 Oct 2011 08:40:14 GMT
Accept-Ranges: bytes
ETag: &amp;quot;bc46bae1ba93cc1:0&amp;quot;
Server: Microsoft-IIS/7.5
Date: Sun, 04 Dec 2011 11:14:54 GMT
Connection: close
Content-Length: 37
Pr0t3ct!on#cyber_security@12*12.2011+Connection closed by foreign host.
$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I reworked &lt;a href="keyfetch.py"&gt;keyfetch.py&lt;/a&gt; to make
the fetch using &lt;code&gt;HTTP/1.0&lt;/code&gt; to double check.&lt;/p&gt;
&lt;p&gt;Trying &lt;code&gt;Pr0t3ct!on#cyber_security@12*12.2011+&lt;/code&gt; as the key does indeed
work and produces this page:
&lt;a href="http://www.canyoucrackit.co.uk/soyoudidit.asp"&gt;http://www.canyoucrackit.co.uk/soyoudidit.asp&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So you did it. Well done! Now this is where it gets interesting. Could
you use your skills and ingenuity to combat terrorism and cyber
threats? As one of our experts, you'll help protect our nation's
security and the lives of thousands. Every day will bring new
challenges, new solutions to find -- and new ways to prove that
you're one of the best.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'm not going to apply for a job as I'm rather fully employed
elsewhere, but it was a fun challenge!&lt;/p&gt;
&lt;h1 id="postmortem"&gt;Postmortem&lt;/h1&gt;
&lt;p&gt;I didn't see this until the 1st December 2011 when a colleague at work
(thanks Tom!) mentioned it to me and I didn't have time to work on it
until Friday the 2nd of December. It took me one very late night on
Friday and intermittent hacking on Saturday and Sunday to complete the
challenge - about 12 hours in total. I spent 3 hours tracking down that
mis-understanding in &lt;a href="vm.py"&gt;vm.py&lt;/a&gt; about 16
byte segments and 2 hours trying to work out what the missing 12 bytes
were in the URL in stage 3.&lt;/p&gt;
&lt;p&gt;I think Stage 1 was very hard - perhaps deliberately so. Stage 2 was
much easier - there was a defined goal and any competent computer
scientist would be able to knock up the VM code. Stage 3 involved an
awful lot of reading C compiler created x86 assembler which was painful.
I suspect I could have done it a lot quicker if I'd had some better
tools. An interactive disassembling debugger would have been useful - I
used to have such a thing when I did 68000 programming and it was a
wonder.&lt;/p&gt;
&lt;p&gt;I note that I didn't actually have to crack the encrypted password in
Stage 3. I could have just changed one byte and have it ignore the check
but I was expecting that the code would actually need to use it. Alas no
and so much for &lt;a href="http://www.openwall.com/john/"&gt;John the Ripper&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Finally thanks to GCHQ for making the challenge - it was a good one!&lt;/p&gt;</description></item><item><title>Pi - Chudnovsky</title><link>https://ncw.github.io/www/articles/pi-chudnovsky/</link><pubDate>Sat, 08 Oct 2011 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/pi-chudnovsky/</guid><description>&lt;p&gt;In &lt;a href="https://ncw.github.io/www/nick/articles/pi-machin/"&gt;Part 3&lt;/a&gt; we managed to calculate 1,000,000
decimal places of π with
&lt;a href="http://en.wikipedia.org/wiki/John_Machin"&gt;Machin&lt;/a&gt;'s &lt;code&gt;arctan&lt;/code&gt; formula.
Our stated aim was 100,000,000 places which we are going to achieve now!&lt;/p&gt;
&lt;div class="card float-right" style="max-width: 18rem;"&gt;
&lt;div class="card-header" style="padding: 5px 10px;"&gt;
Fun with Maths and Python
&lt;/div&gt;
&lt;div class="card-body"&gt;
This is a having fun with maths and python article. See &lt;a href="https://ncw.github.io/www/nick/articles/fun-with-maths-and-python-introduction/"&gt;the
introduction&lt;/a&gt;
for important information!
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We have still got a long way to go though, and we'll have to improve
both our algorithm (formula) for π and our implementation.&lt;/p&gt;
&lt;p&gt;The current darling of the π world is the &lt;a href="http://en.wikipedia.org/wiki/Chudnovsky_algorithm"&gt;Chudnovsky
algorithm&lt;/a&gt; which is
similar to the &lt;code&gt;arctan&lt;/code&gt; formula but it converges much quicker. It is
also rather complicated. The formula itself is derived from one by
&lt;a href="http://www-history.mcs.st-and.ac.uk/Biographies/Ramanujan.html"&gt;Ramanjuan&lt;/a&gt;
who's work was extraordinary in the extreme. It isn't trivial to
prove, so I won't! Here is Chudnovsky's formula for π as it is usually
stated:&lt;/p&gt;
&lt;div&gt;$$
\frac{1}{\pi} = 12 \sum^\infty_{k=0} \frac{(-1)^k (6k)! (13591409 + 545140134k)}{(3k)!(k!)^3 640320^{3k + 3/2}}
$$&lt;/div&gt;
&lt;p&gt;That is quite a complicated formula, we will make more comprehensible in
a moment. If you haven't seen the Σ notation before it just like a
&lt;code&gt;sum&lt;/code&gt; over a &lt;code&gt;for&lt;/code&gt; loop in python. For example:&lt;/p&gt;
&lt;div&gt;$$
\sum^{10}_{k=1} k^2
$$&lt;/div&gt;
&lt;p&gt;Is exactly the same as this python fragment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sum(k&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; k &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First let's get rid of that funny fractional power:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
\frac{1}{\pi} &amp;= 12 \sum^\infty_{k=0} \frac{(-1)^k (6k)! (13591409 + 545140134k)}{(3k)!(k!)^3 640320^{3k + 3/2}} \\
&amp;= \frac{12}{640320 \sqrt{640320}} \sum^\infty_{k=0} \frac{(-1)^k (6k)! (13591409 + 545140134k)}{(3k)!(k!)^3 640320^{3k}} \\
&amp;= \frac{1}{426880 \sqrt{10005}} \sum^\infty_{k=0} \frac{(-1)^k (6k)! (13591409 + 545140134k)}{(3k)!(k!)^3 640320^{3k}} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Now let's split it into two independent parts. See how there is a &lt;code&gt;+&lt;/code&gt;
sign inside the Σ? We can split it into two series which we will call
&lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; and work out what π is in terms of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
a &amp;= \sum^\infty_{k=0} \frac{(-1)^k (6k)!}{(3k)!(k!)^3 640320^{3k}} \\
&amp;= 1
- \frac{6\cdot5\cdot4}{(1)^3 640320^3}
+ \frac{12\cdot11\cdot10\cdot9\cdot8\cdot7}{(2\cdot1)^3 640320^6}
- \frac{18\cdot17\cdots13}{(3\cdot2\cdot1)^3 640320^{9}}
+ \cdots \\
b &amp;= \sum^\infty_{k=0} \frac{(-1)^k (6k)!k}{(3k)!(k!)^3 640320^{3k}} \\
\frac{1}{\pi} &amp;= \frac{13591409a + 545140134b}{426880 \sqrt{10005}} \\
\pi &amp;= \frac{426880 \sqrt{10005}}{13591409a + 545140134b}
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Finally note that we can calculate the next &lt;code&gt;a&lt;/code&gt; term from the previous
one, and the &lt;code&gt;b&lt;/code&gt; terms from the &lt;code&gt;a&lt;/code&gt; terms which simplifies the
calculations rather a lot.&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
a_k &amp;= \frac{(-1)^k (6k)!}{(3k)!(k!)^3 640320^{3k}} \\
b_k &amp;= k \cdot a_k \\
\frac{a_{k}}{a_{k-1}} &amp;= - \frac{(6k-5)(6k-4)(6k-3)(6k-2)(6k-1)6k}{3k(3k-1)(3k-2)k^3 640320^3} \\
&amp;= - \frac{24(6k-5)(2k-1)(6k-1)}{k^3 640320^3} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;OK that was a lot of maths! But it is now in an easy to compute state,
which we can do like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_chudnovsky&lt;/span&gt;(one&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Calculate pi using Chudnovsky&amp;#39;s series
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; This calculates it in fixed point, using the value for one passed in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; k &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a_k &lt;span style="color:#f92672"&gt;=&lt;/span&gt; one
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a_sum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; one
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b_sum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; C &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;640320&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; C3_OVER_24 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; C&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a_k &lt;span style="color:#f92672"&gt;*=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;k&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;k&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;k&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a_k &lt;span style="color:#f92672"&gt;//=&lt;/span&gt; k&lt;span style="color:#f92672"&gt;*&lt;/span&gt;k&lt;span style="color:#f92672"&gt;*&lt;/span&gt;k&lt;span style="color:#f92672"&gt;*&lt;/span&gt;C3_OVER_24
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; a_sum &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; a_k
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b_sum &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; k &lt;span style="color:#f92672"&gt;*&lt;/span&gt; a_k
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; k &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; a_k &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13591409&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a_sum &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;545140134&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;b_sum
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pi &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;426880&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;sqrt(&lt;span style="color:#ae81ff"&gt;10005&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;one, one)&lt;span style="color:#f92672"&gt;*&lt;/span&gt;one) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; total
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; pi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We need to be able to take the square root of long integers which python
doesn't have a built in for. Luckily this is easy to provide. This uses
a &lt;a href="http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number"&gt;square root algorithm devised by
Newton&lt;/a&gt;
which doubles the number of significant places in the answer (quadratic
convergence) each iteration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sqrt&lt;/span&gt;(n, one):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Return the square root of n as a fixed point number with the one
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; passed in. It uses a second order Newton-Raphson convergence. This
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; doubles the number of significant figures on each iteration.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Use floating point arithmetic to make an initial guess&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; floating_point_precision &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n_float &lt;span style="color:#f92672"&gt;=&lt;/span&gt; float((n &lt;span style="color:#f92672"&gt;*&lt;/span&gt; floating_point_precision) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; one) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; floating_point_precision
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (int(floating_point_precision &lt;span style="color:#f92672"&gt;*&lt;/span&gt; math&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sqrt(n_float)) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; one) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; floating_point_precision
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n_one &lt;span style="color:#f92672"&gt;=&lt;/span&gt; n &lt;span style="color:#f92672"&gt;*&lt;/span&gt; one
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x_old &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; n_one &lt;span style="color:#f92672"&gt;//&lt;/span&gt; x) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; x &lt;span style="color:#f92672"&gt;==&lt;/span&gt; x_old:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It uses normal floating point arithmetic to make an initial guess then
refines it using Newton's method.&lt;/p&gt;
&lt;p&gt;See &lt;a href="pi_chudnovsky.py"&gt;pi_chudnovsky.py&lt;/a&gt; for the
complete program. When I run it I get this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Digits&lt;/th&gt;
&lt;th&gt;Time (seconds)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;4.696e-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;0.0001530&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;0.002027&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;0.08685&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;8.453&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;956.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Which is nearly 3 times quicker than the best result in &lt;a href="https://ncw.github.io/www/nick/articles/pi-machin/"&gt;part
3&lt;/a&gt;, and gets us 1,000,000 places of π in
about 15 minutes.&lt;/p&gt;
&lt;p&gt;Amazingly there are still two major improvements we can make to this.
The first is to recast the calculation using something called &lt;a href="http://numbers.computation.free.fr/Constants/Algorithms/splitting.html"&gt;binary
splitting&lt;/a&gt;.
Binary splitting is a general purpose technique for speeding up this
sort of calculation. What it does is convert the sum of the individual
fractions into one giant fraction. This means that you only do one
divide at the end of the calculation which speeds things up greatly,
because division is slow compared to multiplication.&lt;/p&gt;
&lt;p&gt;Consider the general infinite series&lt;/p&gt;
&lt;div&gt;$$
S(0,\infty) = \frac{a_0p_0}{b_0q_0}
+ \frac{a_1p_0p_1}{b_1q_0q_1}
+ \frac{a_2p_0p_1p_2}{b_2q_0q_1q_2}
+ \frac{a_3p_0p_1p_2p_3}{b_3q_0q_1q_2q_3}
+ \cdots
$$&lt;/div&gt;
&lt;p&gt;This could be used as a model for all the infinite series we've looked
at so far. Now lets consider the partial sum of that series from terms
&lt;code&gt;a&lt;/code&gt; to &lt;code&gt;b&lt;/code&gt; (including a, not including b).&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
S(a,b) &amp;= \frac{a_ap_a}{b_aq_a}
+ \frac{a_{a+1}p_ap_{a+1}}{b_{a+1}q_aq_{a+1}}
+ \frac{a_{a+2}p_ap_{a+1}p_{a+2}}{b_{a+2}q_aq_{a+1}q_{a+2}}
+ \cdots
+ \frac{a_{b-1}p_ap_{a+1}p_{a+2}\cdots p_{b-1}}{b_{b-1}q_aq_{a+1}\cdots p_{b-1}} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;This is a part of the infinite series, and if a=0 and b=∞ it becomes the
infinite series above.&lt;/p&gt;
&lt;p&gt;Now lets define some extra functions:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
P(a,b) &amp;= p_ap_{a+1}\cdots p_{b-1} \\
Q(a,b) &amp;= q_aq_{a+1}\cdots q_{b-1} \\
B(a,b) &amp;= b_ab_{a+1}\cdots b_{b-1} \\
T(a,b) &amp;= B(a,b)Q(a,b)S(a,b) \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Let's define m which is a &amp;lt;= m &amp;lt;= b. Making m as near to the middle
of a and b will lead to the quickest calculations, but for the proof, it
has to be somewhere between them. Lets work out what happens to our
variables P, Q, R and T when we split the series in two:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
P(a,b) &amp;= P(a,m)P(b,m) \\
Q(a,b) &amp;= Q(a,m)Q(b,m) \\
B(a,b) &amp;= B(a,m)B(b,m) \\
T(a,b) &amp;= B(m,b)Q(m,b)T(a,m) + B(a,m)P(a,m)T(m,b) \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;The first three of those statements are obvious from the definitions,
but the last deserves proof.&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
&amp; B(m,b)Q(m,b)T(a,m) + B(a,m)P(a,m)T(m,b) &amp;&amp; \left[T(a,b) = B(a,b)Q(a,b)S(a,b)\right] \\
&amp;= B(m,b)Q(m,b)B(a,m)Q(a,m)S(a,m) + B(a,m)P(a,m)B(m,b)Q(m,b)S(m,b) &amp;&amp; \left[Q(a,b) = Q(a,m)Q(b,m)\right] \\
&amp; &amp;&amp; \left[B(a,b) = B(a,m)B(b,m)\right] \\
&amp;= B(a,b)Q(a,b)S(a,m) + B(a,b)P(a,m)Q(m,b)S(m,b) \\
&amp;= B(a,b)(Q(a,b)S(a,m) + P(a,m)Q(m,b)S(m,b)) &amp;&amp; \left[Q(m,b) = \frac{Q(a,b)}{Q(a,m)}\right] \\
&amp;= B(a,b)\left(Q(a,b)S(a,m) + \frac{Q(a,b)P(a,m)}{Q(a,m)}S(m,b)\right) \\
&amp;= B(a,b)Q(a,b)\left(S(a,m) + \frac{P(a,m)}{Q(a,m)}S(m,b)\right) \\
&amp;= B(a,b)Q(a,b)\left(
\frac{a_ap_a}{b_aq_a}
+ \frac{a_{a+1}p_ap_{a+1}}{b_{a+1}q_aq_{a+1}}
+ \frac{a_{a+2}p_ap_{a+1}p_{a+2}}{b_{a+2}q_aq_{a+1}q_{a+2}}
+ \cdots
+ \frac{a_{m-1}p_ap_{a+1}p_{a+2}\cdots p_{m-1}}{b_{m-1}q_aq_{a+1}\cdots p_{m-1}}
+ \frac{p_ap_{a+1}\cdots p_{m-1}}{q_aq_{a+1}\cdots q_{m-1}}
+ \left(\frac{a_mp_m}{b_mq_m}
+ \frac{a_{m+1}p_mp_{m+1}}{b_{m+1}q_mq_{m+1}}
+ \frac{a_{m+2}p_mp_{m+1}p_{m+2}}{b_{m+2}q_mq_{m+1}q_{m+2}}
+ \cdots
+ \frac{a_{b-1}p_mp_{m+1}p_{m+2}\cdots p_{b-1}}{b_{b-1}q_mq_{m+1}\cdots p_{b-1}}
\right)\right) \\
&amp;= B(a,b)Q(a,b)\left(
\frac{a_ap_a}{b_aq_a}
+ \frac{a_{a+1}p_ap_{a+1}}{b_{a+1}q_aq_{a+1}}
+ \frac{a_{a+2}p_ap_{a+1}p_{a+2}}{b_{a+2}q_aq_{a+1}q_{a+2}}
+ \cdots
+ \frac{a_{m-1}p_ap_{a+1}p_{a+2}\cdots p_{m-1}}{b_{m-1}q_aq_{a+1}\cdots p_{m-1}}
+ \frac{p_ap_{a+1}\cdots p_{m-1}}{q_aq_{a+1}\cdots q_{m-1}}
+ \frac{a_mp_ap_{a+1}\cdots p_m}{b_mq_aq_{a+1}\cdots q_m}
+ \frac{a_{m+1}p_ap_{a+1}\cdots p_{m+1}}{b_{m+1}q_aq_{a+1}\cdots q_{m+1}}
+ \frac{a_{m+2}p_ap_{a+1}\cdots p_{m+2}}{b_{m+2}q_aq_{a+1}\cdots q_{m+2}}
+ \cdots
+ \frac{a_{b-1}p_ap_{a+1}\cdots p_{b-1}}{b_{b-1}q_aq_{a+1}\cdots p_{b-1}}
\right) \\
&amp;= B(a,b)Q(a,b)S(a,b) \\
&amp;= T(a,b) \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;We can use these relations to expand the series recursively, so if we
want S(0,8) then we can work out S(0,4) and S(4,8) and combine them.
Likewise to calculate S(0,4) and S(4,8) we work out S(0,2), S(2,4),
S(4,6), S(6,8) and combine them, and to work out those we work out
S(0,1), S(1,2), S(2,3), S(3,4), S(4,5), S(5,6), S(6,7), S(7,8). Luckily
we don't have to split them down any more as we know what P(a,a+1),
Q(a,a+1) etc is from the definition above.&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
P(a,a+1) &amp;= p_a \\
Q(a,a+1) &amp;= q_a \\
B(a,a+1) &amp;= b_a \\
S(a,a+1) &amp;= \frac{a_ap_a}{b_aq_a} \\
T(a,a+1) &amp;= B(a,a+1)Q(a,a+1)S(a,a+1) \\
&amp;= b_aq_a\frac{a_ap_a}{b_aq_a} \\
&amp;= a_ap_a \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;And when you've finally worked out P(0,n),Q(0,n),B(0,n),T(0,n) you can
work out S(0,n) with&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
S(0,n) &amp;= \frac{T(0,n)}{B(0,n)Q(0,n)} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;If you want a more detailed and precise treatment of binary splitting
then see &lt;a href="http://www.ginac.de/CLN/binsplit.pdf"&gt;Bruno Haible and Thomas Papanikolaou's
paper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So back to Chudnovksy's series. We can now set these parameters in the
above general formula:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
p_0 &amp;= 1 \\
p_a &amp;= (6a-5)(2a-1)(6a-1) \\
q_0 &amp;= 1 \\
q_a &amp;= a^3\cdot640320^3/24 \\
b_a &amp;= 1 \\
a_a &amp;= (13591409 + 545140134a) \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;This then makes our Chudnovksy pi function look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_chudnovsky_bs&lt;/span&gt;(digits):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Compute int(pi * 10**digits)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; This is done using Chudnovsky&amp;#39;s series with binary splitting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; C &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;640320&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; C3_OVER_24 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; C&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bs&lt;/span&gt;(a, b):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Computes the terms for binary splitting the Chudnovsky infinite series
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; a(a) = +/- (13591409 + 545140134*a)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; p(a) = (6*a-5)*(2*a-1)*(6*a-1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; b(a) = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; q(a) = a*a*a*C3_OVER_24
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; returns P(a,b), Q(a,b) and T(a,b)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; b &lt;span style="color:#f92672"&gt;-&lt;/span&gt; a &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Directly compute P(a,a+1), Q(a,a+1) and T(a,a+1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; a &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Qab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Qab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;C3_OVER_24
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Pab &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;13591409&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;545140134&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a) &lt;span style="color:#75715e"&gt;# a(a) * p(a)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; a &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;Tab
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Recursively compute P(a,b), Q(a,b) and T(a,b)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# m is the midpoint of a and b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; b) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Recursively calculate P(a,m), Q(a,m) and T(a,m)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pam, Qam, Tam &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bs(a, m)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Recursively calculate P(m,b), Q(m,b) and T(m,b)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pmb, Qmb, Tmb &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bs(m, b)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Now combine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Pam &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Pmb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Qab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Qam &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Qmb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Qmb &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Tam &lt;span style="color:#f92672"&gt;+&lt;/span&gt; Pam &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Tmb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; Pab, Qab, Tab
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# how many terms to compute&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DIGITS_PER_TERM &lt;span style="color:#f92672"&gt;=&lt;/span&gt; math&lt;span style="color:#f92672"&gt;.&lt;/span&gt;log10(C3_OVER_24&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; N &lt;span style="color:#f92672"&gt;=&lt;/span&gt; int(digits&lt;span style="color:#f92672"&gt;/&lt;/span&gt;DIGITS_PER_TERM &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Calclate P(0,N) and Q(0,N)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; P, Q, T &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bs(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, N)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; one &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;**&lt;/span&gt;digits
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sqrtC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sqrt(&lt;span style="color:#ae81ff"&gt;10005&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;one, one)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (Q&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;426880&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;sqrtC) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; T
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hopefully you'll see how the maths above relates to this as I've used
the same notation in each. Note that we calculate the number of digits
of pi we expect per term of the series (about 14.18) to work out how
many terms of the series we need to compute, as the binary splitting
algorithm needs to know in advance how many terms to calculate. We also
don't bother calculating &lt;code&gt;B(a)&lt;/code&gt; as it is always &lt;code&gt;1&lt;/code&gt;. Defining a
function inside a function like this makes what is known as a closure.
This means that the inner function can access the variables in the outer
function which is very convenient in this recursive algorithm as it
stops us having to pass the constants to every call of the function.&lt;/p&gt;
&lt;p&gt;See &lt;a href="pi_chudnovsky_bs.py"&gt;pi_chudnovsky_bs.py&lt;/a&gt; for
the complete program. When I run it I get this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Digits&lt;/th&gt;
&lt;th&gt;Time (seconds)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1.096e-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;3.194e-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;0.0004899&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;0.03403&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;3.625&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;419.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is a bit more than twice as fast as
&lt;a href="pi_chudnovsky.py"&gt;pi_chudnovsky.py&lt;/a&gt; giving us our
1,000,000 places in just under 7 minutes. If you profile it you'll
discover that almost all the time spent in the square root calculations
(86% of the time) whereas only 56 seconds is spent in the binary
splitting part. We could spend time improving the square root algorithm,
but it is time to bring out the big guns: gmpy.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.google.com/p/gmpy/"&gt;Gmpy&lt;/a&gt; is a python interface to the
&lt;a href="http://gmplib.org/"&gt;gmp library&lt;/a&gt; which is a C library for arbitrary
precision arithmetic. It is very fast, much faster than the built in
&lt;code&gt;int&lt;/code&gt; type in python for large numbers. Luckily gmpy provides a type
(&lt;code&gt;mpz&lt;/code&gt;) which works exactly like normal python &lt;code&gt;int&lt;/code&gt; types, so we have
to make hardly any changes to our code to use it. These are using
initialising variables with the &lt;code&gt;mpz&lt;/code&gt; type, and using the &lt;code&gt;sqrt&lt;/code&gt; method
on &lt;code&gt;mpz&lt;/code&gt; rather than our own home made &lt;code&gt;sqrt&lt;/code&gt; algorithm:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; math
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; gmpy2 &lt;span style="color:#f92672"&gt;import&lt;/span&gt; mpz
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; time &lt;span style="color:#f92672"&gt;import&lt;/span&gt; time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_chudnovsky_bs&lt;/span&gt;(digits):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Compute int(pi * 10**digits)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; This is done using Chudnovsky&amp;#39;s series with binary splitting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; C &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;640320&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; C3_OVER_24 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; C&lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bs&lt;/span&gt;(a, b):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Computes the terms for binary splitting the Chudnovsky infinite series
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; a(a) = +/- (13591409 + 545140134*a)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; p(a) = (6*a-5)*(2*a-1)*(6*a-1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; b(a) = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; q(a) = a*a*a*C3_OVER_24
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; returns P(a,b), Q(a,b) and T(a,b)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; b &lt;span style="color:#f92672"&gt;-&lt;/span&gt; a &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Directly compute P(a,a+1), Q(a,a+1) and T(a,a+1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; a &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Qab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mpz(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mpz((&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Qab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mpz(a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a&lt;span style="color:#f92672"&gt;*&lt;/span&gt;C3_OVER_24)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Pab &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;13591409&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;545140134&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;a) &lt;span style="color:#75715e"&gt;# a(a) * p(a)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; a &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;Tab
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Recursively compute P(a,b), Q(a,b) and T(a,b)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# m is the midpoint of a and b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; b) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Recursively calculate P(a,m), Q(a,m) and T(a,m)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pam, Qam, Tam &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bs(a, m)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Recursively calculate P(m,b), Q(m,b) and T(m,b)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pmb, Qmb, Tmb &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bs(m, b)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Now combine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Pab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Pam &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Pmb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Qab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Qam &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Qmb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tab &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Qmb &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Tam &lt;span style="color:#f92672"&gt;+&lt;/span&gt; Pam &lt;span style="color:#f92672"&gt;*&lt;/span&gt; Tmb
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; Pab, Qab, Tab
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# how many terms to compute&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DIGITS_PER_TERM &lt;span style="color:#f92672"&gt;=&lt;/span&gt; math&lt;span style="color:#f92672"&gt;.&lt;/span&gt;log10(C3_OVER_24&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; N &lt;span style="color:#f92672"&gt;=&lt;/span&gt; int(digits&lt;span style="color:#f92672"&gt;/&lt;/span&gt;DIGITS_PER_TERM &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Calclate P(0,N) and Q(0,N)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; P, Q, T &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bs(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, N)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; one_squared &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mpz(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;)&lt;span style="color:#f92672"&gt;**&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;digits)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sqrtC &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;10005&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;one_squared)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sqrt()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (Q&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;426880&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;sqrtC) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; T
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See
&lt;a href="pi_chudnovsky_bs_gmpy.py"&gt;pi_chudnovsky_bs_gmpy.py&lt;/a&gt;
for the complete program. When I run it I get this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Digits&lt;/th&gt;
&lt;th&gt;Time (seconds)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1.597e-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;3.409e-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;0.003403&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;0.003571&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;0.09120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;1.760&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000000&lt;/td&gt;
&lt;td&gt;30.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100000000&lt;/td&gt;
&lt;td&gt;542.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So we have achieved our goal of calculating 100,000,000 places of π in
just under 10 minutes! What is limiting the program now is memory...
100,000,000 places takes about 600MB of memory to run. With 6 GB of free
memory it could probably calculate one billion places in a few hours.&lt;/p&gt;
&lt;p&gt;What if we wanted to go faster? Well you could use
&lt;a href="ftp://ftp.gmplib.org/pub/misc/gmp-chudnovsky.c"&gt;gmp-chudnovsky.c&lt;/a&gt; which
is a C program which implements the Chudnovsky Algorithm. It is heavily
optimised and rather difficult to understand, but if you untangle it
you'll see it does exactly the same as above, with one extra twist. The
twist is that it factors the fraction in the binary splitting phase as
it goes along. If you examine the &lt;a href="http://gmplib.org/pi-with-gmp.html"&gt;gmp-chudnovsky.c
results&lt;/a&gt; page you'll see that the
little python program above acquits itself very well - the python
program only takes 75% longer than the optimised C program on the same
hardware.&lt;/p&gt;
&lt;p&gt;One algorithm which has the potential to beat Chudnovsky is the
&lt;a href="http://en.wikipedia.org/wiki/Gauss-Legendre_algorithm"&gt;Arithmetic Geometric
Mean&lt;/a&gt; algorithm
which doubles the number of decimal places each iteration. It involves
square roots and full precision divisions which makes it tricky to
implement well. In theory it should be faster than Chudnovsk but, so
far, in practice Chudnovsky is faster.&lt;/p&gt;
&lt;p&gt;Here is a chart of all the different π programs we've developed in
&lt;a href="https://ncw.github.io/www/nick/articles/pi-gregorys-series/"&gt;Part 1&lt;/a&gt;, &lt;a href="https://ncw.github.io/www/nick/articles/pi-archimedes/"&gt;Part
2&lt;/a&gt;, &lt;a href="https://ncw.github.io/www/nick/articles/pi-machin/"&gt;Part 3&lt;/a&gt;
and &lt;a href="https://ncw.github.io/www/nick/articles/pi-chudnovsky/"&gt;Part 4&lt;/a&gt; with their timings on my
2010 Intel® Core™ i7 CPU Q820 @ 1.73GHz running 64 bit Linux:&lt;/p&gt;
&lt;p&gt;&lt;img src="pi_timings.png" alt="Chart of timings for calculating π with various methods"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="pi_timings.ods"&gt;Source spreadsheet&lt;/a&gt; for the timings.&lt;/p&gt;</description></item><item><title>Pi - Machin</title><link>https://ncw.github.io/www/articles/pi-machin/</link><pubDate>Tue, 19 Jul 2011 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/pi-machin/</guid><description>&lt;p&gt;In &lt;a href="https://ncw.github.io/www/nick/articles/pi-archimedes/"&gt;Part 2&lt;/a&gt; we managed to calculate 100
decimal places of π with Archimedes' recurrence relation for π which
was a fine result, but we can do bigger and faster.&lt;/p&gt;
&lt;div class="card float-right" style="max-width: 18rem;"&gt;
&lt;div class="card-header" style="padding: 5px 10px;"&gt;
Fun with Maths and Python
&lt;/div&gt;
&lt;div class="card-body"&gt;
This is a having fun with maths and python article. See &lt;a href="https://ncw.github.io/www/nick/articles/fun-with-maths-and-python-introduction/"&gt;the
introduction&lt;/a&gt;
for important information!
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To go faster we'll have to use a two pronged approach - a better
algorithm for π, and a better implementation.&lt;/p&gt;
&lt;p&gt;In 1706 &lt;a href="http://en.wikipedia.org/wiki/John_Machin"&gt;John Machin&lt;/a&gt; came up
with the first really fast method of calculating π and used it to
calculate π to 100 decimal places. Quite an achievement considering he
did that entirely with pencil and paper. Machin's formula is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;π/4 = 4cot⁻¹(5) - cot⁻¹(239)
= 4tan⁻¹(1/5) - tan⁻¹(1/239)
= 4 * arctan(1/5) - arctan(1/239)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can prove Machin's formula using some relatively easy math!
Hopefully you learnt this &lt;a href="http://mathworld.wolfram.com/TrigonometricAdditionFormulas.html"&gt;trigonometric
formula&lt;/a&gt;
at school:&lt;/p&gt;
&lt;div&gt;$$
tan(a + b) = \frac{tan(a) + tan(b)}{1 - tan(a) \cdot tan(b)}
$$&lt;/div&gt;
&lt;p&gt;Substitute &lt;code&gt;a = arctan(x)&lt;/code&gt; and &lt;code&gt;b = arctan(y)&lt;/code&gt; into it, giving:&lt;/p&gt;
&lt;div&gt;$$
tan(arctan(x) + arctan(y)) = \frac{tan(arctan(x)) + tan(arctan(y)}{1 - tan(arctan(x)) \cdot tan(arctan(y))}
$$&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;tan(arctan(x))&lt;/code&gt; = &lt;code&gt;x&lt;/code&gt; which gives:&lt;/p&gt;
&lt;div&gt;$$
tan(arctan(x) + arctan(y)) = \frac{x + y}{1 - xy}
$$&lt;/div&gt;
&lt;p&gt;arctan both sides to get:&lt;/p&gt;
&lt;div&gt;$$
arctan(x) + arctan(y) = arctan\left(\frac{x + y}{1 - xy}\right)
$$&lt;/div&gt;
&lt;p&gt;This gives us a method for adding two &lt;code&gt;arctans&lt;/code&gt;. Using this we can prove
Machin's formula with a bit of help from python's &lt;a href="http://docs.python.org/library/fractions.html"&gt;fractions
module&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from fractions import Fraction
&amp;gt;&amp;gt;&amp;gt; def add_arctan(x, y): return (x + y) / (1 - x * y)
...
&amp;gt;&amp;gt;&amp;gt; a = add_arctan(Fraction(1,5), Fraction(1,5))
&amp;gt;&amp;gt;&amp;gt; a # 2*arctan(1/5)
Fraction(5, 12)
&amp;gt;&amp;gt;&amp;gt; b = add_arctan(a, a)
&amp;gt;&amp;gt;&amp;gt; b # 4*arctan(1/5)
Fraction(120, 119)
&amp;gt;&amp;gt;&amp;gt; c = add_arctan(b, Fraction(-1,239))
&amp;gt;&amp;gt;&amp;gt; c # 4*arctan(1/5) - arctan(1/239)
Fraction(1, 1)
&amp;gt;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So Machin's formula is equal to &lt;code&gt;arctan(1/1)&lt;/code&gt; = π/4 QED! Or if you
prefer it written out in mathematical notation:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
4arctan\left(\frac{1}{5}\right) - arctan\left(\frac{1}{239}\right)
&amp;= 2\left(arctan\left(\frac{1}{5}\right) + arctan\left(\frac{1}{5}\right)\right) - arctan\left(\frac{1}{239}\right) \\
&amp;= 2arctan\left(\frac{5}{12}\right) - arctan\left(\frac{1}{239}\right) \\
&amp;= arctan\left(\frac{5}{12}\right) + arctan\left(\frac{5}{12}\right) - arctan\left(\frac{1}{239}\right) \\
&amp;= arctan\left(\frac{120}{119}\right) - arctan\left(\frac{1}{239}\right) \\
&amp;= arctan\left(\frac{1}{1}\right) \\
&amp;= \frac{\pi}{4} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;So how do we use Machin's formula to calculate π? Well first we need to
calculate &lt;code&gt;arctan(x)&lt;/code&gt; which sounds complicated, but we've seen the
infinite series for it already in &lt;a href="https://ncw.github.io/www/nick/articles/pi-gregorys-series/"&gt;Part
1&lt;/a&gt; :&lt;/p&gt;
&lt;div&gt;$$
arctan(x) = x - \frac{x^3}{3} + \frac{x^5}{5} - \frac{x^7}{7} + \frac{x^9}{9} - \cdots ( -1 &lt;= x &lt;= 1 )
$$&lt;/div&gt;
&lt;p&gt;We can see that if x=1/5 then the terms get smaller very quickly, which
means that the series will converge quickly. Let's substitute &lt;code&gt;x = 1/x&lt;/code&gt;
and get:&lt;/p&gt;
&lt;div&gt;$$
arctan(1/x) = \frac{1}{x} - \frac{1}{3x^3} + \frac{1}{5x^5} - \frac{1}{7x^7} + \frac{1}{9x^9} - \cdots ( x &gt;= 1 )
$$&lt;/div&gt;
&lt;p&gt;Each term in the series is created by dividing the previous term by a
small integer. Dividing two 100 digit numbers is hard work as I'm sure
you can imagine from your experiences with long division at school!
However it is much easier to divide a short number (a single digit) into
a 100 digit number. We called this short division at school, and that is
the key to making a much faster π algorithm. In fact if you are dividing
an N digit number by an M digit number it takes rougly N*M operations.
That square root we did in &lt;a href="https://ncw.github.io/www/nick/articles/pi-archimedes/"&gt;Part 2&lt;/a&gt; did
dozens of divisions of 200 digit numbers. So if we could somehow
represent the current term in a &lt;code&gt;int&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; then we could use this speedy
division to greatly speed up the calculation.&lt;/p&gt;
&lt;p&gt;The way we do that is to multiply everything by a large number, lets say
10&lt;sup&gt;100&lt;/sup&gt;. We then do all our calculations with integers, knowing that we
should shift the decimal place 100 places to the left when done to get
the answer. This needs a little bit of care, but is a well known
technique known as fixed point arithmetic.&lt;/p&gt;
&lt;p&gt;The definition of the &lt;code&gt;arctan(1/x)&lt;/code&gt; function then looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;arctan&lt;/span&gt;(x, one&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Calculate arctan(1/x)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; arctan(1/x) = 1/x - 1/3*x**3 + 1/5*x**5 - ... (x &amp;gt;= 1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; This calculates it in fixed point, using the value for one passed in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; power &lt;span style="color:#f92672"&gt;=&lt;/span&gt; one &lt;span style="color:#f92672"&gt;//&lt;/span&gt; x &lt;span style="color:#75715e"&gt;# the +/- 1/x**n part of the term&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;=&lt;/span&gt; power &lt;span style="color:#75715e"&gt;# the total so far&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x_squared &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; x &lt;span style="color:#75715e"&gt;# precalculate x**2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; divisor &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#75715e"&gt;# the 1,3,5,7 part of the divisor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; power &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; power &lt;span style="color:#f92672"&gt;//&lt;/span&gt; x_squared
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; divisor &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; delta &lt;span style="color:#f92672"&gt;=&lt;/span&gt; power &lt;span style="color:#f92672"&gt;//&lt;/span&gt; divisor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; delta &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; total
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The value &lt;code&gt;one&lt;/code&gt; passed in is the multiplication factor as described
above. You can think of it as representing &lt;code&gt;1&lt;/code&gt; in the fixed point
arithmetic world. Note the use of the &lt;code&gt;//&lt;/code&gt; operator which does integer
divisions. If you don't use this then python will make floating point
values&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;. In the loop there are two divisions, &lt;code&gt;power // x_squared&lt;/code&gt;
and &lt;code&gt;power // divisor&lt;/code&gt;. Both of these will be dividing by small numbers,
&lt;code&gt;x_squared&lt;/code&gt; will be 5² = 25 or 239² = 57121 and &lt;code&gt;divisor&lt;/code&gt; will be 2 *
the number of iterations which again will be small.&lt;/p&gt;
&lt;p&gt;So how does this work in practice? On my machine it calculates 100
digits of π in 0.18 ms which is over 30,000 times faster than the
previous calculation with the decimal module in &lt;a href="https://ncw.github.io/www/nick/articles/pi-archimedes/"&gt;Part
2&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Can we do better?&lt;/p&gt;
&lt;p&gt;Well the answer is yes! Firstly there are better arctan formulae.
Amazingly there are other formulae which will calculate π too, like
these, which are named after their inventors:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_machin&lt;/span&gt;(one):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;arctan(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, one) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; arctan(&lt;span style="color:#ae81ff"&gt;239&lt;/span&gt;, one))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_ferguson&lt;/span&gt;(one):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;arctan(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, one) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; arctan(&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;, one) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; arctan(&lt;span style="color:#ae81ff"&gt;1985&lt;/span&gt;, one))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_hutton&lt;/span&gt;(one):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;arctan(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, one) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; arctan(&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, one))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_gauss&lt;/span&gt;(one):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;arctan(&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;, one) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;arctan(&lt;span style="color:#ae81ff"&gt;57&lt;/span&gt;, one) &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;arctan(&lt;span style="color:#ae81ff"&gt;239&lt;/span&gt;, one))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It turns out that Machin's formula is really very good, but Gauss's
formula is slightly better.&lt;/p&gt;
&lt;p&gt;The other way we can do better is to use a better formula for
&lt;code&gt;arctan()&lt;/code&gt;. &lt;a href="http://en.wikipedia.org/wiki/Leonhard_Euler"&gt;Euler&lt;/a&gt; came up
with this &lt;a href="http://mathworld.wolfram.com/InverseTangent.html"&gt;accelerated formula for
arctan&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;$$
arctan(1/x) = \frac{x}{1+x^2}
+ \frac{2}{3}\frac{x}{(1+x^2)^2}
+ \frac{2\cdot4}{3\cdot5}\frac{x}{(1+x^2)^3}
+ \frac{2\cdot4\cdot6}{3\cdot5\cdot7}\frac{x}{(1+x^2)^4}
+ \cdots
$$&lt;/div&gt;
&lt;p&gt;This converges to &lt;code&gt;arctan(1/x)&lt;/code&gt; at the roughly the same rate per term
than the formula above, however each term is made directly from the
previous term by multiplying by &lt;code&gt;2n&lt;/code&gt; and dividing by &lt;code&gt;(2n+1)(1+x²)&lt;/code&gt;.
This means that it can be implemented with only one (instead of two)
divisions per term, and hence runs roughly twice as quickly. If we
implement this in python in fixed point, then it looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;arctan_euler&lt;/span&gt;(x, one&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000000&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Calculate arctan(1/x) using euler&amp;#39;s accelerated formula
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; This calculates it in fixed point, using the value for one passed in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x_squared &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x_squared_plus_1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x_squared &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; term &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; one) &lt;span style="color:#f92672"&gt;//&lt;/span&gt; x_squared_plus_1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;=&lt;/span&gt; term
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; two_n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; divisor &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (two_n&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; x_squared_plus_1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; term &lt;span style="color:#f92672"&gt;*=&lt;/span&gt; two_n
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; term &lt;span style="color:#f92672"&gt;=&lt;/span&gt; term &lt;span style="color:#f92672"&gt;//&lt;/span&gt; divisor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; term &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; term
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; two_n &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; total
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how we pre-calculate as many things as possible (like
&lt;code&gt;x_squared_plus_1&lt;/code&gt;) to get them out of the loop.&lt;/p&gt;
&lt;p&gt;See the complete program:
&lt;a href="https://ncw.github.io/www/nick/pub/pymath/pi_arctan_integer.py"&gt;pi_artcan_integer.py&lt;/a&gt;. Here
are some timings&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt; of how the Machin and the Gauss arctan formula
fared, with and without the accelerated arctan.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Formula&lt;/th&gt;
&lt;th&gt;Digits&lt;/th&gt;
&lt;th&gt;Normal Arctan (seconds)&lt;/th&gt;
&lt;th&gt;Euler Arctan (seconds)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Machin&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;3.004e-05&lt;/td&gt;
&lt;td&gt;2.098e-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gauss&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;2.098e-05&lt;/td&gt;
&lt;td&gt;1.907e-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Machin&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;0.0001869&lt;/td&gt;
&lt;td&gt;0.0001471&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gauss&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;0.0001869&lt;/td&gt;
&lt;td&gt;0.0001468&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Machin&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;0.005599&lt;/td&gt;
&lt;td&gt;0.003520&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gauss&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;0.005398&lt;/td&gt;
&lt;td&gt;0.003445&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Machin&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;0.3995&lt;/td&gt;
&lt;td&gt;0.2252&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gauss&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;0.3908&lt;/td&gt;
&lt;td&gt;0.2186&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Machin&lt;/td&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;38.33&lt;/td&gt;
&lt;td&gt;21.69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gauss&lt;/td&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;37.44&lt;/td&gt;
&lt;td&gt;21.12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Machin&lt;/td&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;3954.1&lt;/td&gt;
&lt;td&gt;2396.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gauss&lt;/td&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;3879.4&lt;/td&gt;
&lt;td&gt;2402.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are several interesting things to note. Firstly that we just
calculated 1,000,000 decimal places of π in 40 minutes! Secondly that to
calculate 10 times as many digits it takes 100 times as long. This means
that our algorithm scales as O(n²) where n is the number of digits. So
if 1,000,000 digits takes an hour, 10,000,000 would take 100 hours (4
days) and 100,000,000 would take 400 days (13 months). Your computer
might run out of memory, or explode in some other fashion when
calculating 100,000,000 digits, but doesn't seem impossible any more.&lt;/p&gt;
&lt;p&gt;The Gauss formula is slightly faster than the Machin for nearly all the
results. The accelerated arctan formula is 1.6 times faster than the
normal arctan formula so that is a definite win.&lt;/p&gt;
&lt;p&gt;A billion (1,000,000,000) digits of pi would take about 76 years to
calculate using this program which is a bit out of our reach! There are
several ways we could improve this. If we could find an algorithm for
calculating π which was quicker than O(n²), or if we could find an O(n²)
algorithm which just ran a lot faster. We could also throw more CPUs at
the problem. To see how this might be done, we could calculate all the
odd terms on one processor, and all the even terms on another processor
for the &lt;code&gt;arctan&lt;/code&gt; formula and add them together at the end.. That would
run just about twice as quickly. That could easily be generalised to
lots of processors:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;arctan(1/x) = 1/x - 1/3x³ + 1/5x⁵ - 1/7x⁷ + ...
= 1/x + 1/5x⁵ - + ... # run on cpu 1
+ - 1/3x³ - 1/7x⁷ + ... # run on cpu 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So if we had 76 CPU cores, we could probably calculate π to
1,000,000,000 places in about a year.&lt;/p&gt;
&lt;p&gt;There are better algorithms for calculating π though, and there are
faster ways of doing arithmetic than python's built in long integers.
We'll explore both in &lt;a href="https://ncw.github.io/www/nick/articles/pi-chudnovsky/"&gt;Part 4&lt;/a&gt;!&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Python's integer type was called called &lt;code&gt;long&lt;/code&gt; in python 2, just
&lt;code&gt;int&lt;/code&gt; in python 3&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Unless you are using python 2&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;All timings generated on my 2010 Intel® Core™ i7 CPU Q820 @
1.73GHz running 64 bit Linux&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Pi - Archimedes</title><link>https://ncw.github.io/www/articles/pi-archimedes/</link><pubDate>Mon, 18 Jul 2011 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/pi-archimedes/</guid><description>&lt;p&gt;It is clear from &lt;a href="https://ncw.github.io/www/nick/articles/pi-gregorys-series/"&gt;Part 1&lt;/a&gt; that in
order to calculate π we are going to need a better method than
evaluating &lt;a href="http://mathworld.wolfram.com/GregorySeries.html"&gt;Gregory's
Series&lt;/a&gt;.&lt;/p&gt;
&lt;div class="card float-right" style="max-width: 18rem;"&gt;
&lt;div class="card-header" style="padding: 5px 10px;"&gt;
Fun with Maths and Python
&lt;/div&gt;
&lt;div class="card-body"&gt;
This is a having fun with maths and python article. See &lt;a href="https://ncw.github.io/www/nick/articles/fun-with-maths-and-python-introduction/"&gt;the
introduction&lt;/a&gt;
for important information!
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Here is one which was originally discovered by Archimedes in 200BC. Most
of the proofs for series for calculating π require calculus or other
advanced math, but since Archimedes didn't know any of those you can
prove it without! In fact I thought I had discovered it for the first
time when I was 13 or so, but alas I was 2000 years too late!&lt;/p&gt;
&lt;p&gt;Archimedes knew that the ratio of the circumference of a circle to its
diameter was π. He had the idea that he could draw a regular polygon
inscribed within the circle to approximate π, and the more sides he drew
on the polygon, the better approximation to π he would get. In modern
maths speak, we would say as the number of sides of the polygon tends to
infinity, the circumference tends to 2π.&lt;/p&gt;
&lt;p&gt;Instead of drawing the polygon though, Archimedes calculated the length
using a geometric argument, like this.&lt;/p&gt;
&lt;p&gt;&lt;img src="pi_geometric_proof.png" alt="Diagram for proof of Archimedes π formula"&gt;&lt;/p&gt;
&lt;p&gt;Draw a circle of radius 1 unit centered at A. Inscribe an N sided
polygon within it. Our estimate for π is half the circumference of the
polygon (circumference of a circle is 2πr, r = 1, giving 2π). As the
sides of the polygon get smaller and smaller the circumference gets
closer and closer to 2π.&lt;/p&gt;
&lt;p&gt;The diagram shows one segment of the polygon ACE. The side of the
polygon CE has length d&lt;sub&gt;n&lt;/sub&gt;. Assuming we know d for an N sided polygon,
If we can find an expression for the length CD = d&lt;sub&gt;2n&lt;/sub&gt;, the edge length
of a polygon with 2N sides, in terms of d&lt;sub&gt;n&lt;/sub&gt; only, then we can improve
our estimate for π. Let's try to do that.&lt;/p&gt;
&lt;p&gt;We bisect the triangle CAE to make CAD and DAE the two new equal
segments of the 2N sided polygon.&lt;/p&gt;
&lt;p&gt;Using Pythagoras's theorem on the right angled triangle ABC, we can
see:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
AB^2 + BC^2 &amp;= 1^2 = 1 \\
AB &amp;= \sqrt{1 - BC^2} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Given that&lt;/p&gt;
&lt;div&gt;$$
BC = \frac{d_n}{2}
$$&lt;/div&gt;
&lt;p&gt;Substituting gives&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
AB &amp;= \sqrt{1-\left(\frac{d_n}{2}\right)^2} \\
BD &amp;= 1 - AB \\
&amp;= 1 - \sqrt{1-\frac{d_n^2}{4}} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Using Pythagoras's theorem on the right angled triangle CBD&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
CD^2 &amp;= BC^2 + BD^2 \\
&amp;= \left(\frac{d_n}{2}\right)^2 + \left(1 - \sqrt{1-\left(\frac{d_n}{2}\right)^2}\right)^2 \\
&amp;= \frac{d_n^2}{4} + \left(1 - 2\sqrt{1-\frac{d_n^2}{4}} + \left(1 - \frac{d_n^2}{4}\right)\right) \\
&amp;= 2 - 2\sqrt{1-\frac{d_n^2}{4}} \\
CD &amp;= d_{2n} \\
&amp;= \sqrt{2 - 2\sqrt{1-\frac{d_n^2}{4}}} \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;d&lt;sub&gt;2n&lt;/sub&gt; is the length of one side of the polygon with 2N sides.&lt;/p&gt;
&lt;p&gt;This means that if we know the length of the sides of a polygon with N
sides, then we can calculate the length of the sides of a polygon with
2N sides.&lt;/p&gt;
&lt;p&gt;What does this mean? Lets start with a square. Inscribing a square in a
circle looks like this, with the side length √2. This gives an estimate
for π as 2√2, which is poor (at 2.828) but it is only the start of the
process.&lt;/p&gt;
&lt;p&gt;&lt;img src="pi_geometric_inscribed_square.png" alt="Square inscribed in a circle"&gt;&lt;/p&gt;
&lt;p&gt;We can the calculate the side length of an octagon, from the side length
of a square, and the side length of a 16-gon from an octagon etc.&lt;/p&gt;
&lt;p&gt;&lt;img src="pi_geometric_inscribed_polygons.png" alt="Polygons inscribed in a circle"&gt;&lt;/p&gt;
&lt;p&gt;It's almost time to break out python, but before we do so, we'll just
note that to calculate d&lt;sub&gt;2n&lt;/sub&gt; from d&lt;sub&gt;n&lt;/sub&gt;, the first thing you do is
calculate d² and at the very end you take the square root. This kind of
suggests that it would be better to keep track of d² rather than d,
which we do in the program below
(&lt;a href="pi_archimedes.py"&gt;pi_archimedes.py&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; math
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_archimedes&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Calculate n iterations of Archimedes PI recurrence relation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_edge_length_squared &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_sides &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_edge_length_squared &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; math&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sqrt(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; polygon_edge_length_squared &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_sides &lt;span style="color:#f92672"&gt;*=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; polygon_sides &lt;span style="color:#f92672"&gt;*&lt;/span&gt; math&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sqrt(polygon_edge_length_squared) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Try the series
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; n &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pi_archimedes(n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; result &lt;span style="color:#f92672"&gt;-&lt;/span&gt; math&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pi
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%8d&lt;/span&gt;&lt;span style="color:#e6db74"&gt; iterations &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%.10f&lt;/span&gt;&lt;span style="color:#e6db74"&gt; error &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%.10f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; (n, result, error))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you run this, then it produces:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iterations&lt;/th&gt;
&lt;th&gt;Sides&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2.8284271247&lt;/td&gt;
&lt;td&gt;-0.3131655288&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;3.0614674589&lt;/td&gt;
&lt;td&gt;-0.0801251947&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;3.1214451523&lt;/td&gt;
&lt;td&gt;-0.0201475013&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;3.1365484905&lt;/td&gt;
&lt;td&gt;-0.0050441630&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;3.1403311570&lt;/td&gt;
&lt;td&gt;-0.0012614966&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;3.1412772509&lt;/td&gt;
&lt;td&gt;-0.0003154027&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;td&gt;3.1415138011&lt;/td&gt;
&lt;td&gt;-0.0000788524&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;td&gt;3.1415729404&lt;/td&gt;
&lt;td&gt;-0.0000197132&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;td&gt;3.1415877253&lt;/td&gt;
&lt;td&gt;-0.0000049283&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;2048&lt;/td&gt;
&lt;td&gt;3.1415914215&lt;/td&gt;
&lt;td&gt;-0.0000012321&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;4096&lt;/td&gt;
&lt;td&gt;3.1415923456&lt;/td&gt;
&lt;td&gt;-0.0000003080&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;8192&lt;/td&gt;
&lt;td&gt;3.1415925765&lt;/td&gt;
&lt;td&gt;-0.0000000770&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;16384&lt;/td&gt;
&lt;td&gt;3.1415926335&lt;/td&gt;
&lt;td&gt;-0.0000000201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;32768&lt;/td&gt;
&lt;td&gt;3.1415926548&lt;/td&gt;
&lt;td&gt;0.0000000012&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;65536&lt;/td&gt;
&lt;td&gt;3.1415926453&lt;/td&gt;
&lt;td&gt;-0.0000000083&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;131072&lt;/td&gt;
&lt;td&gt;3.1415926074&lt;/td&gt;
&lt;td&gt;-0.0000000462&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Hooray! We calculated π to 8 decimal places in only 13 iterations.
Iteration 0 for the square shows up the expected 2.828 estimate for π.
You can see after iteration 13 that the estimate of π starts getting
worse. That is because we only calculated all our calculations to the
limit of precision of python's &lt;a href="http://docs.python.org/tutorial/floatingpoint.html"&gt;floating point
numbers&lt;/a&gt; (about 17
digits), and all those errors start adding up.&lt;/p&gt;
&lt;p&gt;We can easily calculate more digits of π using Pythons excellent
&lt;a href="http://docs.python.org/library/decimal.html"&gt;decimal module&lt;/a&gt;. This
allows you to do arbitrary precision arithmetic on numbers. It isn't
particularly quick, but it is built in and easy to use.&lt;/p&gt;
&lt;p&gt;Let's calculate π to 100 decimal places now. That sounds like a
significant milestone!
(&lt;a href="pi_archimedes_decimal.py"&gt;pi_archimedes_decimal.py&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; decimal &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Decimal, getcontext
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_archimedes&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Calculate n iterations of Archimedes PI recurrence relation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_edge_length_squared &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Decimal(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_sides &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_edge_length_squared &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; polygon_edge_length_squared &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sqrt()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; polygon_sides &lt;span style="color:#f92672"&gt;*=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; polygon_sides &lt;span style="color:#f92672"&gt;*&lt;/span&gt; polygon_edge_length_squared&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sqrt()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Try the series
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; places &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; old_result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; n &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;places):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Do calculations with double precision&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; getcontext()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;prec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;places
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pi_archimedes(n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Print the result with single precision&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; getcontext()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;prec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; places
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;result &lt;span style="color:#75715e"&gt;# do the rounding on result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%3d&lt;/span&gt;&lt;span style="color:#e6db74"&gt;: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%s&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; (n, result))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; result &lt;span style="color:#f92672"&gt;==&lt;/span&gt; old_result:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; old_result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You'll see if you look at the &lt;code&gt;pi_archimedes&lt;/code&gt; function that not a lot
has changed. Instead of using the &lt;code&gt;math.sqrt&lt;/code&gt; function we use the &lt;code&gt;sqrt&lt;/code&gt;
method of the &lt;code&gt;Decimal&lt;/code&gt; object. The edge gets initialised to
&lt;code&gt;Decimal(2)&lt;/code&gt; rather than &lt;code&gt;2.0&lt;/code&gt; but otherwise the methods are the same.
The &lt;code&gt;main&lt;/code&gt; method has changed a bit. You'll see that we set the
precision of the decimal calculations using the
&lt;code&gt;getcontext().prec = ...&lt;/code&gt; call. This sets the precision for all
following calculations. There are other ways to do this which you can
see in the &lt;a href="http://docs.python.org/library/decimal.html"&gt;decimal module&lt;/a&gt;
docs. We do the Archimedes calculations with 200 decimal places
precision, then print the result out with 100 decimal places precision
by changing the precision and using the &lt;code&gt;result = +result&lt;/code&gt; trick. When
the result stops changing we end, because that must be π!&lt;/p&gt;
&lt;p&gt;If you run this, you'll find at iteration 168 it produces 100
accurately rounded decimal places of π. So far so good!&lt;/p&gt;
&lt;p&gt;There are two downsides to this function though. One is that the decimal
arithmetic is quite slow. On my computer it takes about 6 seconds to
calculate 100 digits of π which sounds fast, but if you were to try for
1,000,000 places you would be waiting a very very long time! The other
problem is the square root. Square roots are expensive operations, they
take lots of multiplications and divisions and we need to do away with
that to go faster.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://ncw.github.io/www/nick/articles/pi-machin/"&gt;Part 3&lt;/a&gt; we'll be getting back to the
infinite series for &lt;code&gt;arctan&lt;/code&gt; and on to much larger numbers of digits of
π.&lt;/p&gt;</description></item><item><title>Pi - Gregory's Series</title><link>https://ncw.github.io/www/articles/pi-gregorys-series/</link><pubDate>Sun, 17 Jul 2011 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/pi-gregorys-series/</guid><description>&lt;p&gt;Lets calculate π (or Pi if you prefer)! π is an irrational number
(amongst other things) which means that it isn't one whole number
divided by another whole number. In fact the digits of π are extremely
random - if you didn't know they were the digits of π they would be
perfectly random.&lt;/p&gt;
&lt;div class="card float-right" style="max-width: 18rem;"&gt;
&lt;div class="card-header" style="padding: 5px 10px;"&gt;
Fun with Maths and Python
&lt;/div&gt;
&lt;div class="card-body"&gt;
This is a having fun with maths and python article. See &lt;a href="https://ncw.github.io/www/nick/articles/fun-with-maths-and-python-introduction/"&gt;the
introduction&lt;/a&gt;
for important information!
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;π has been calculated to billions of decimal places, but in this series
of articles, we're going to aim for the more modest target of
100,000,000 decimal places calculated by a python program in a
reasonable length of time. We are going to try some different formulae
and algorithms following a roughly historical path.&lt;/p&gt;
&lt;p&gt;You were probably taught at school that 22/7 is a reasonable
approximation to π. Maybe you were even taught that 355/113 was a better
one. You were unlikely to have been taught how π is actually calculated.
You could draw a circle and measure the circumference, but that is very
hard to do accurately.&lt;/p&gt;
&lt;p&gt;Luckily maths comes to the rescue. There are 100s of formulae for
calculating π, but the simplest one I know of is this:&lt;/p&gt;
&lt;div&gt;$$
\frac{\pi}{4} = 1 - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \frac{1}{9} - \frac{1}{11} + \frac{1}{13} - \frac{1}{15} + \frac{1}{17} - \cdots
$$&lt;/div&gt;
&lt;p&gt;This is known as &lt;a href="http://mathworld.wolfram.com/GregorySeries.html"&gt;Gregory's
Series&lt;/a&gt; (or sometimes
the Leibnitz formula) for π. That &lt;code&gt;...&lt;/code&gt; stands for keep going forever.
To make the next term in the series, alternate the sign, and add 2 to
the denominator of the fraction, so &lt;code&gt;+ 1/19&lt;/code&gt; is next then &lt;code&gt;- 1/21&lt;/code&gt; etc.&lt;/p&gt;
&lt;p&gt;To see why this is true, we need to look at the
&lt;a href="http://mathworld.wolfram.com/LeibnizSeries.html"&gt;Leibnitz&lt;/a&gt; formula for
&lt;code&gt;arctan&lt;/code&gt; (or &lt;code&gt;tan⁻¹&lt;/code&gt;). This is:&lt;/p&gt;
&lt;div&gt;$$
arctan(x) = x - \frac{x^3}{3} + \frac{x^5}{5} - \frac{x^7}{7} + \frac{x^9}{9} - \cdots ( -1 &lt;= x &lt;= 1 )
$$&lt;/div&gt;
&lt;p&gt;Note that the result of &lt;code&gt;arctan(x)&lt;/code&gt; is in radians. I'm not going to
prove that formula here as it involves calculus, but you can see &lt;a href="http://www.math.wpi.edu/IQP/BVCalcHist/calc3.html"&gt;a
proof of the arctan
formula&lt;/a&gt; if you want.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;arctan&lt;/code&gt; is the inverse of &lt;code&gt;tan&lt;/code&gt;, so &lt;code&gt;arctan(tan(x)) = x&lt;/code&gt;. &lt;code&gt;tan(x)&lt;/code&gt; is
the familiar (hopefully) ratio of the opposite and adjacent sides of a
right angled triangle and how that relates to the angle.&lt;/p&gt;
&lt;p&gt;If we set the angle to 45°, which is π/4 radians, then:&lt;/p&gt;
&lt;div&gt;$$
\begin{align}
tan(45°) &amp;= 1 \\
⇒ tan(\pi/4) &amp;= 1 \\
⇒ arctan(1) &amp;= \pi/4 \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;which when substituted in the above becomes:&lt;/p&gt;
&lt;div&gt;$$
\frac{\pi}{4} = 1 - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \frac{1}{9} - \cdots
$$&lt;/div&gt;
&lt;p&gt;This may be the simplest infinite series formula for π but it has the
disadvantage that you'll need to add up a great number of terms to get
an acceptably accurate answer.&lt;/p&gt;
&lt;p&gt;Here is a bit of python to calculate it
(&lt;a href="pi_gregory.py"&gt;pi_gregory.py&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-py3" data-lang="py3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; math
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi_gregory&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Calculate n iterations of Gregory&amp;#39;s series
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; divisor &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sign &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; sign &lt;span style="color:#f92672"&gt;/&lt;/span&gt; divisor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; divisor &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sign &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;sign
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Try Gregory&amp;#39;s series
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; log_n &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#f92672"&gt;**&lt;/span&gt;log_n
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pi_gregory(n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; result &lt;span style="color:#f92672"&gt;-&lt;/span&gt; math&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pi
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%8d&lt;/span&gt;&lt;span style="color:#e6db74"&gt; iterations &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%.10f&lt;/span&gt;&lt;span style="color:#e6db74"&gt; error &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%.10f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; (n, result, error))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All the important stuff happens in &lt;code&gt;pi_gregory&lt;/code&gt; and hopefully you'll
see how that relates to the infinite series for &lt;code&gt;arctan&lt;/code&gt;. Note the trick
of keeping the sign of the term in a variable as &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;-1&lt;/code&gt; and then
multiplying by this. This is a common trick, easier to write than an if
statement and probably faster.&lt;/p&gt;
&lt;p&gt;The program above prints:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Iterations&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;3.0418396189&lt;/td&gt;
&lt;td&gt;-0.0997530347&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;3.1315929036&lt;/td&gt;
&lt;td&gt;-0.0099997500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;3.1405926538&lt;/td&gt;
&lt;td&gt;-0.0009999997&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;3.1414926536&lt;/td&gt;
&lt;td&gt;-0.0001000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;3.1415826536&lt;/td&gt;
&lt;td&gt;-0.0000100000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000000&lt;/td&gt;
&lt;td&gt;3.1415916536&lt;/td&gt;
&lt;td&gt;-0.0000010000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000000&lt;/td&gt;
&lt;td&gt;3.1415925536&lt;/td&gt;
&lt;td&gt;-0.0000001000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That looks like our old friend π doesn't it! However you can see that
it takes 10 times as many iterations to add another decimal place of
accuracy to the result. That isn't going to get us even 10 decimal
places in a reasonable length of time... We'll have to get a bit
cleverer. (If the program printed out something very different then you
need to run it with python 3 not python 2 see &lt;a href="https://ncw.github.io/www/nick/articles/fun-with-maths-and-python-introduction/"&gt;the
introduction&lt;/a&gt;.)
You can also see something very odd in the error terms - the result is
correct to 10 decimal places, all except for one digit. This is a known
oddity and you can read up about it &lt;a href="http://en.wikipedia.org/wiki/Leibniz_formula_for_pi"&gt;The Leibniz formula for
pi&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;Those of you paying attention will have noted that we used &lt;code&gt;math.pi&lt;/code&gt;
from the python standard library in the above program to calculate the
difference of the result from π. So python already knows the value of π!
However that is only a double precison value (17 digits or so) and we
are aiming for much more. We are going to leave the world of double
precision floating point behind, and calculate a lot more digits of π,
much quicker, in the next exciting episode (&lt;a href="https://ncw.github.io/www/nick/articles/pi-archimedes/"&gt;Part
2&lt;/a&gt;)!&lt;/p&gt;</description></item><item><title>Fun with Maths and Python - Introduction</title><link>https://ncw.github.io/www/articles/fun-with-maths-and-python-introduction/</link><pubDate>Sat, 16 Jul 2011 00:00:00 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/fun-with-maths-and-python-introduction/</guid><description>&lt;p&gt;This is going to be a series of articles which are all about having fun
with maths and &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;. I'm going to show you
a bit of maths and then how to apply it with a python program, then work
out how to improve it.&lt;/p&gt;
&lt;p&gt;I decided to write these after looking in my doodles folder on my
computer and finding 100s of programs to calculate this bit of maths, or
explore that bit of maths, and I thought it would be interesting for me
to share them. Hopefully you'll find it interesting too!&lt;/p&gt;
&lt;p&gt;I'm going to use python 3 for all python code. This enables me to
future proof these articles and encourage everyone who hasn't tried
Python 3 to have a go. The programs will run with minor modifications on
python 2 - just watch out for &lt;a href="http://www.python.org/dev/peps/pep-0238/"&gt;division which has changed from python 2
to 3&lt;/a&gt;. In fact if you run any
of these programs under python 2 then put
&lt;code&gt;from __future__ import division&lt;/code&gt; at the top of them.&lt;/p&gt;
&lt;p&gt;Python is a really excellent language for investigations into maths. It
is easy to read and has excellent long number support with infinite
precision integers and the &lt;a href="http://docs.python.org/library/decimal.html"&gt;decimal
module&lt;/a&gt;. I'm going to
attempt to demonstrate what I want to demonstrate not using any third
party modules, but I may occasionally use the &lt;a href="https://code.google.com/p/gmpy/"&gt;gmpy
module&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm going to pitch the level of maths below calculus, no more than the
maths that everyone should have learnt at school. If I want to use some
bit of maths outside that range I'll explain it first. This does means
that sometimes I won't be able to show a proof for things, but I'll
add a link to an online proof if I can find one.&lt;/p&gt;
&lt;p&gt;You are going to see maths written both in traditional style:&lt;/p&gt;
&lt;div&gt;$$
x=\frac{-b \pm \sqrt {b^2-4ac}}{2a}
$$&lt;/div&gt;
&lt;p&gt;And in computer style which every programmer knows anyway. This involves
a few more brackets, but it is much easier to translate to computer
code. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(-b +/- sqrt(b**2 - 4*a*c)) / (2*a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Python computer maths we write:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;*&lt;/code&gt; to mean multiply&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt; to mean divide&lt;/li&gt;
&lt;li&gt;&lt;code&gt;**&lt;/code&gt; to mean to the power&lt;/li&gt;
&lt;li&gt;&lt;code&gt;//&lt;/code&gt; to mean divide but give the result as an integer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%&lt;/code&gt; to mean the same as the &lt;code&gt;modulo&lt;/code&gt; or &lt;code&gt;mod&lt;/code&gt; operator, ie do the division and take the remainder.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm going to make free with unicode fonts so you'll see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;π - pi&lt;/li&gt;
&lt;li&gt;x² - x squared&lt;/li&gt;
&lt;li&gt;√x - square root of x&lt;/li&gt;
&lt;li&gt;± - plus or minus&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If these aren't appearing properly, then you'll need to try a
different browser, or install some more fonts.&lt;/p&gt;
&lt;p&gt;As for the programming level, anyone who knows a little bit of python
should be able to work out what is happening - I won't be doing
anything too fancy!&lt;/p&gt;
&lt;p&gt;I'll tag all the articles with
&lt;a href="https://ncw.github.io/www/nick/articles/category/pymath/"&gt;pymath&lt;/a&gt; so you can find them or
subscribe to the &lt;a href="https://ncw.github.io/www/nick/articles/category/pymath/feed"&gt;rss&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy Calculating!&lt;/p&gt;
&lt;p&gt;Nick Craig-Wood&lt;/p&gt;
&lt;p&gt;&lt;a href="mailto:nick@craig-wood.com"&gt;nick@craig-wood.com&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Technology changes in 2010</title><link>https://ncw.github.io/www/articles/2010-changes-in-tech/</link><pubDate>Wed, 22 Dec 2010 14:56:39 +0000</pubDate><author>nick@craig-wood.com (Nick Craig-Wood)</author><guid>https://ncw.github.io/www/articles/2010-changes-in-tech/</guid><description>&lt;p&gt;Technology that has come and gone from my life in 2010, and new stuff
I've learnt. More than I expected!&lt;/p&gt;
&lt;p&gt;These notes are really for me to look back at over the years, but you
might find them interesting.&lt;/p&gt;
&lt;h1 id="old"&gt;Old&lt;/h1&gt;
&lt;p&gt;Things gone from my life. Gone but not forgotten :-&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.mutt.org/"&gt;Mutt&lt;/a&gt; - finally replaced with
&lt;a href="http://www.mozillamessaging.com/en-GB/thunderbird/"&gt;Thunderbird&lt;/a&gt;.
Mutt is a terminal based email client, just in case you haven't
heard of it. It works really well for power users, is really
configurable, but in these days of HTML emails and attachments it
was no longer keeping up. I loved him - he was a faithful mutt,
but he had to go. (Actually he is still there at the command line
ready to go if needed - but keep it under your hat!)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.google.co.uk/images?q=courier+modem"&gt;Courier V34
modem&lt;/a&gt; - years
overdue, I finally disconnected it and consigned it to the pit of
oblivion. It used to receive faxes, but I don't think anyone has
sent one for several years. It also used to run a BBS and an
Internet node, which was useful at times, but now GPRS/3G/Wifi is
everywhere I want to go it is no longer needed.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Integrated_Services_Digital_Network"&gt;ISDN&lt;/a&gt; -
128k of digital goodness just wasn't good enough any more and
became too expensive. Great in its hey-day with 2 channels, 10
numbers and a whopping 64k digitial Internet connection. Obsoleted
by ADSL and
&lt;a href="http://www.gradwell.com/phoneservices/enterprise"&gt;VOIP&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nokia.co.uk/find-products/all-phones/nokia-e90-communicator"&gt;Nokia
E90&lt;/a&gt;
&amp;amp; &lt;a href="http://en.wikipedia.org/wiki/Symbian_OS"&gt;Symbian&lt;/a&gt; - sorry...
we've had good times, but I've found someone else&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.kde.org/"&gt;KDE&lt;/a&gt; - you worked really well until version
4 where the bugs and the slowness really kicked in.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikimedia.org/wiki/Usenet"&gt;Usenet&lt;/a&gt; - This was my first
hint of online communities on the Internet in 1994. Unfortunately
the cool kids have moved on, and so, reluctantly, have I!&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="new"&gt;New&lt;/h1&gt;
&lt;p&gt;New technology :-&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.mozillamessaging.com/en-GB/thunderbird/"&gt;Thunderbird&lt;/a&gt; -
for people with complicated email lives the plugin system makes
life bearable! Here are my top plugins
&lt;ul&gt;
&lt;li&gt;Nostalgy - adds keyboard shortcuts to save, copy, goto folders&lt;/li&gt;
&lt;li&gt;Quickfolders - Put your favourite folders along the top&lt;/li&gt;
&lt;li&gt;Copy Sent to Current - copy sent mail to the current folder
not the Sent folder - makes a new and better way of doing
email&lt;/li&gt;
&lt;li&gt;Display Mail User Agent - snoop on what other people use for
their mail client&lt;/li&gt;
&lt;li&gt;Enigmail - Use PGP to sign/encrypt your emails seamlessly&lt;/li&gt;
&lt;li&gt;External Editor - edit emails in your favourite editor (eg
emacs)&lt;/li&gt;
&lt;li&gt;Identity Chooser - If you use multiple identities you need
this!&lt;/li&gt;
&lt;li&gt;Mail Redirect - proper bounce of email (not forward)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/UW_IMAP"&gt;IMAP&lt;/a&gt; -
makes it easy to migrate your email setup. You can still use it
with procmail so some things haven't changed ;-) I can use it
with my Android phone and the excellent
&lt;a href="https://code.google.com/p/k9mail/"&gt;K9Mail&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.blogofile.com"&gt;Blogofile&lt;/a&gt; - which makes this (fully
static) website. It replaces a pile of crufty hand built python
scripts which did the same thing, just not nearly as well!&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; on the desktop - I finally gave
in and replaced &lt;a href="http://http://www.debian.org/"&gt;Debian&lt;/a&gt; testing
with &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; on my main laptop so I can
spend less time fixing stuff and more time doing real work! Debian
still rules on the server though.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.gradwell.com/phoneservices/enterprise"&gt;VOIP&lt;/a&gt; - I've
signed up with a 100% Voip provider and migrated my 10 telephone
numbers to them. It went reasonably smoothly! I took the ISDN card
out of my Asterisk PBX. We've been doing this at work for ages -
it seemed like time to migrate at home too.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.android.org/"&gt;Android&lt;/a&gt; - is Google's new phone
operating system. It runs on Linux and is mostly open source which
are big positives in my view. I've been enjoying my Android phone
greatly and have written a number of applications -
&lt;a href="http://www.craig-wood.com/nick/android/oxo3d/"&gt;Oxo3d&lt;/a&gt; is one.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.gnome.org/"&gt;Gnome&lt;/a&gt; - well not new actually, I last
gave Gnome up in about 2005 when I got irritated at no longer
being able to edit my menus. Unfortunately KDE 4 isn't shaping up
for me, so it is hello again!&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="books"&gt;Books&lt;/h1&gt;
&lt;p&gt;Tech books I've read this year. No python books this year - I think
I've read them all now!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.amazon.co.uk/dp/0596007736/?tag=niccrawoosweb-21"&gt;Java in a
Nutshell&lt;/a&gt;
(again) programming to write Android programs. I learnt original
Java ages ago, but is is quite a different experience with generic
types. Still not my favourite language - reminds me too much of
C++, but bearable.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.co.uk/dp/0981531601/?tag=niccrawoosweb-21"&gt;Programming In
Scala&lt;/a&gt; -
just for fun - maybe I'll use it with Android one day. Scala is
one of the new breed of languages which runs on the Java VM. Scala
is a (mostly) functional language created by one of the creators
of Java itself.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.co.uk/dp/0596520123/?tag=niccrawoosweb-21"&gt;Version Control with
Git&lt;/a&gt; -
distributed revision control system. Very clever idea with lots
and lots of command lines to explore. If it scales to the Linux
kernel then surely it is good enough for my projects?&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.co.uk/dp/0596002548/?tag=niccrawoosweb-21"&gt;BGP: Building Reliable Networks with the Border Gateway
Protocol&lt;/a&gt; -
how the Internet really works!&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.co.uk/dp/1933988673/?tag=niccrawoosweb-21"&gt;Unlocking Android: A Developer's
Guide&lt;/a&gt; -
how to make Android applications&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.co.uk/dp/1590595270/?tag=niccrawoosweb-21"&gt;Running
IPv6&lt;/a&gt; -
yes it &lt;em&gt;is&lt;/em&gt; coming - IPv4 addresses are running out very soon.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are affiliate links, so if you click then buy I'll earn a few
pence towards my next tech book!&lt;/p&gt;</description></item></channel></rss>