<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1818931634557321641</id><updated>2011-10-15T17:07:56.772+01:00</updated><category term='algebra'/><category term='uni'/><category term='git'/><category term='personal'/><category term='python'/><category term='compsoc'/><category term='google code jam'/><category term='maths'/><category term='coding'/><category term='terrain'/><category term='algorithms'/><category term='quick reference'/><category term='soc'/><category term='x264'/><title type='text'>Journal of Simon Horlick</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-4839945551566645839</id><published>2011-06-28T18:32:00.001+01:00</published><updated>2011-06-28T18:33:52.894+01:00</updated><title type='text'>Setting up keys for GPG</title><content type='html'>gpg --export-secret-keys --armor simonhorlick@gmail.com &gt; simonhorlick-private.asc

gpg --export --armor simonhorlick@gmail.com &gt; simonhorlick-public.asc

gpg --gen-revoke simonhorlick@gmail.com &gt; simonhorlick-revoke.asc&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-4839945551566645839?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/4839945551566645839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2011/06/setting-up-keys-for-gpg.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/4839945551566645839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/4839945551566645839'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2011/06/setting-up-keys-for-gpg.html' title='Setting up keys for GPG'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/14131346374179414632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_m_p17BzLUjU/TU10daizPGI/AAAAAAAAACQ/iZ6wLv9IEcY/s1600/166457_499035046606_686346606_6569389_5308626_n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-862932900073006620</id><published>2010-11-16T12:58:00.000Z</published><updated>2010-11-16T12:58:47.065Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='compsoc'/><title type='text'>How to set up git hosting on COMPSOC</title><content type='html'>&lt;p&gt;If you already have a local git repository that you want to host on compsoc, then you can skip this first step.&lt;/p&gt;

&lt;p&gt;Initialise a new git repository in the directory of the project you want to host (this will be the copy you have at home, for example)
&lt;pre&gt;[simon@simon ~]$ cd ~/project/foo/
[simon@simon foo (master #)]$ git init
Initialized empty Git repository in /home/simon/project/foo/.git/
&lt;/pre&gt;

&lt;p&gt;Log in to compsoc, and create a new directory where you want your repository stored and initialise a bare git repository there.&lt;/p&gt;

&lt;pre&gt;[simon@forgetful ~]$ mkdir foo.git
[simon@forgetful ~]$ cd foo.git/
[simon@forgetful foo.git]$ git --bare init
Initialized empty Git repository in /data/home/simon/foo.git/
[simon@forgetful foo.git (BARE:master)]$&lt;/pre&gt;

&lt;p&gt;On your home machine you will need to add compsoc as a remote, here I've referred to compsoc as "origin".&lt;/p&gt;

&lt;pre&gt;[simon@simon foo (master #)]$ git remote add origin simon@forgetful.compsoc.man.ac.uk:foo.git
&lt;/pre&gt;

&lt;p&gt;Do some editing, commit some changes locally (i.e. at home).&lt;/p&gt;

&lt;pre&gt;[simon@simon foo (master #)]$ vim hello_world.c
[simon@simon foo (master #)]$ git add hello_world.c
[simon@simon foo (master #)]$ git commit -m "Added test file"
[master (root-commit) 76e25d7] Added test file
 1 files changed, 7 insertions(+), 0 deletions(-)
 create mode 100644 hello_world.c
&lt;/pre&gt;

&lt;p&gt;Use git push to push your local changes to compsoc.&lt;/p&gt;

&lt;pre&gt;[simon@simon foo (master)]$ git push origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 302 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To simon@forgetful.compsoc.man.ac.uk:foo.git
 * [new branch]      master -&gt; master
&lt;/pre&gt;

&lt;p&gt;If you want to put your git repository on the internet, either copy or symlink the foo.git directory to be in your public_html directory and run git update-server-info.&lt;/p&gt;

&lt;pre&gt;[simon@forgetful public_html]$ cd ~/public_html/
[simon@forgetful public_html]$ ln -s ../foo.git/
[simon@forgetful ~]$ cd foo.git/
[simon@forgetful foo.git (BARE:master)]$ git --bare update-server-info
[simon@forgetful foo.git (BARE:master)]$ chmod a+x hooks/post-update
&lt;/pre&gt;

&lt;p&gt;Now anyone can come along and clone your git repository.&lt;/p&gt;

&lt;pre&gt;[simon@simon ~]$ cd /tmp
[simon@simon tmp]$ git clone http://compsoc.man.ac.uk/~simon/foo.git
Cloning into foo...
[simon@simon tmp]$ cd foo/
[simon@simon foo (master)]$ cat hello_world.c
#include &lt;stdio.h&gt;

int main() {
    printf("hello, world!\n");
    return 0;
}

&lt;/pre&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-862932900073006620?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/862932900073006620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2010/11/how-to-set-up-git-hosting-on-compsoc.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/862932900073006620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/862932900073006620'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2010/11/how-to-set-up-git-hosting-on-compsoc.html' title='How to set up git hosting on COMPSOC'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-4989025254173406043</id><published>2010-09-25T22:10:00.001+01:00</published><updated>2010-10-08T11:48:39.474+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='soc'/><category scheme='http://www.blogger.com/atom/ns#' term='x264'/><title type='text'>CABAC</title><content type='html'>&lt;p&gt;Context-adaptive binary arithmetic coding is (very roughly) a lossless
compression method that relies on knowlege of the current state of decoding to
make probabalistic decisions about what value for a certain element is about to
come next. For example, if the previous ten macroblocks were all interlaced then
there's a good chance the next one will be too, and it will cost more bits to
signal that the next macroblock isn't interlaced.&lt;/p&gt;

&lt;p&gt;This mostly already worked for mbaff due to the way the code was designed. The
most major part was understanding that the decoder might not have recieved field
decoding flag by the time the code to determine whether a macroblock is
skipped runs. The skip code relied on neighbour calculation using the
macroblock's field/frame flag, but the decoder didn't yet know this. 
Thus x264 needed to store what the decoder thinks the field decoding flag is and
update it only when it's actually written to the bitstream.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-4989025254173406043?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/4989025254173406043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2010/09/cabac.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/4989025254173406043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/4989025254173406043'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2010/09/cabac.html' title='CABAC'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-6468235637821968597</id><published>2010-09-25T21:49:00.000+01:00</published><updated>2010-09-25T21:49:10.279+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='soc'/><category scheme='http://www.blogger.com/atom/ns#' term='x264'/><title type='text'>Motion vectors</title><content type='html'>&lt;p&gt;This I don't understand. Michael Niedermayer (the writer of ffmpeg's h264 decoder) sums up the situation quite succinctly, quoting from &lt;i&gt;libavcodec/h264.h&lt;/i&gt;:
&lt;pre&gt;    /* Wow, what a mess, why didn't they simplify the interlacing &amp; intra
     * stuff, I can't imagine that these complex rules are worth it. */&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;First of all, motion vectors from fields to other fields and frames to other
frames aren't changed. However, when predicting from a frame to a field, the fact
that a field has half the vertical resolution of the frame means that the
vertical component of the motion vector will need to be halved to reference the same
spatial areas. Similarly the motion vector from a field to a frame must be
doubled. This is easily achieved with a few bit shifts (good old integer
arithmetic!) as so:&lt;/p&gt;

&lt;pre&gt;        if( h-&gt;sh.b_mbaff )
        {
#define MAP_MVS\
                MAP_F2F(mv, ref, x264_scan8[0] - 1 - 1*8, h-&gt;mb.i_mb_topleft_xy)\
                MAP_F2F(mv, ref, x264_scan8[0] + 0 - 1*8, top)\
                MAP_F2F(mv, ref, x264_scan8[0] + 1 - 1*8, top)\
                MAP_F2F(mv, ref, x264_scan8[0] + 2 - 1*8, top)\
                MAP_F2F(mv, ref, x264_scan8[0] + 3 - 1*8, top)\
                MAP_F2F(mv, ref, x264_scan8[0] + 4 - 1*8, h-&gt;mb.i_mb_topright_xy)\
                MAP_F2F(mv, ref, x264_scan8[0] - 1 + 0*8, left[0])\
                MAP_F2F(mv, ref, x264_scan8[0] - 1 + 1*8, left[0])\
                MAP_F2F(mv, ref, x264_scan8[0] - 1 + 2*8, left[1])\
                MAP_F2F(mv, ref, x264_scan8[0] - 1 + 3*8, left[1])\
                MAP_F2F(topright_mv, topright_ref, 0, left[0])\
                MAP_F2F(topright_mv, topright_ref, 1, left[0])\
                MAP_F2F(topright_mv, topright_ref, 2, left[1])

            if( h-&gt;mb.b_interlaced )
            {
#define MAP_F2F(varmv, varref, index, macroblock)\
                if( h-&gt;mb.cache.varref[l][index] &gt;= 0 &amp;&amp; !h-&gt;mb.field[macroblock] )\
                {\
                    h-&gt;mb.cache.varref[l][index] &lt;&lt;= 1;\
                    h-&gt;mb.cache.varmv[l][index][1] /= 2;\
                    h-&gt;mb.cache.mvd[l][index][1] &gt;&gt;= 1;\
                }
                MAP_MVS
#undef MAP_F2F
            }
            else
            {
#define MAP_F2F(varmv, varref, index, macroblock)\
                if( h-&gt;mb.cache.varref[l][index] &gt;= 0 &amp;&amp; h-&gt;mb.field[macroblock] )\
                {\
                    h-&gt;mb.cache.varref[l][index] &gt;&gt;= 1;\
                    h-&gt;mb.cache.varmv[l][index][1] &lt;&lt;= 1;\
                    h-&gt;mb.cache.mvd[l][index][1] &lt;&lt;= 1;\
                }
                MAP_MVS
#undef MAP_F2F
            }&lt;/pre&gt;

&lt;p&gt;Here you can see I use a macro to simplify the repeated code, this is actually
inspired by ffmpeg so thanks for the good ideas guys!&lt;/p&gt;

&lt;p&gt;Diagonal motion vectors are bizarre to say the least. Top left motion vectors,
in some situations, are required to come from the middle of the macroblock as
opposed to the usual bottom right location. This was the source of much
frustration for a while. Top right motion vectors, for certain partitions, and
when the top right is unavailable, are taken from strange places in the top left
macroblock.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-6468235637821968597?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/6468235637821968597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2010/09/motion-vectors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/6468235637821968597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/6468235637821968597'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2010/09/motion-vectors.html' title='Motion vectors'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-5266244575553701421</id><published>2010-09-25T21:44:00.000+01:00</published><updated>2010-09-25T21:44:16.521+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='soc'/><category scheme='http://www.blogger.com/atom/ns#' term='x264'/><title type='text'>Intra coding</title><content type='html'>&lt;p&gt;When decoding video it is common that the next macroblock to be decoded will look somewhat like the surrounding macroblocks.
H.264 decodes macroblocks in so called ``scan'' order, i.e. do the first row, left to right, then move on to the next row and repeat.
Imagine a scene with a large section of sky covering the top half of the frame.
A good guess to the content of the next macroblock might be the shade of blue that is directly surrounding it (from the already decoded macroblocks above and to the left).
So we guess that the macroblock we're encoding is blue, then code the difference between that and the actual colour values.
If our macroblock is close to the prediction, which it usually is, then we don't need to code much at all.
This is for the most part how intra coding works. The name comes from the fact that no data outside of the current picture is accessed, as opposed to inter coding that looks at the previous and future frames to help compression.&lt;/p&gt;

&lt;p&gt;MBAFF changes which neighbours need to be referenced when predicting the
next macroblock. This means that it's not usually just the top and left
macroblocks that the pixels for intra prediction come from. The rules for which
macroblock to reference are fairly convoluted, but do make sense from a
compression point of view. I have several pages of diagrams trying to make sense
of it!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-5266244575553701421?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/5266244575553701421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2010/09/intra-coding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/5266244575553701421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/5266244575553701421'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2010/09/intra-coding.html' title='Intra coding'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-6353691679966590801</id><published>2010-04-26T21:21:00.001+01:00</published><updated>2010-09-26T15:27:28.693+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='soc'/><category scheme='http://www.blogger.com/atom/ns#' term='x264'/><title type='text'>Diary of an x264 (mbaff) developer</title><content type='html'>&lt;p&gt;I've just found out officially that I've been accepted into the Summer of Code program! This means that following university exams I'll be working developing a new interlaced encoding method for my favourite video encoder: &lt;a href="http://www.videolan.org/developers/x264.html"&gt;x264&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Interlacing is the process of taking two consecutive pictures (called fields) of video that are often captured slightly after one another and merging them together into a single frame. Many professional video cameras do this in their usual operation. The up-side of this is you can have the high frame rate that comes with presenting two pictures in the space of one, but the downside is that each field has half the vertical resolution of the equivalent frame.&lt;/p&gt;

&lt;p&gt;Macroblock adaptive frame-field interlacing, or mbaff for short, is a method of encoding interlaced video that makes a decision on whether or not each individual macroblock should be interlaced. The traditional method, and that currently implemented in x264, is to keep each frame fully interlaced. However, it is preferable to encode a macroblock with low movement in it as progressive, as this is more efficient. MBAFF interlacing is one of the few major features that most H.264 video encoders currently support that's missing in x264.&lt;/p&gt;

&lt;p&gt;I hope to see significant improvements in the efficiency of interlaced encoding when this project is completed. Until then, I'll post regular updates of my progress.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-6353691679966590801?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/6353691679966590801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2010/04/diary-of-x264-mbaff-developer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/6353691679966590801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/6353691679966590801'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2010/04/diary-of-x264-mbaff-developer.html' title='Diary of an x264 (mbaff) developer'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-6199275379451429546</id><published>2010-03-01T15:25:00.000Z</published><updated>2010-03-01T15:25:35.870Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><category scheme='http://www.blogger.com/atom/ns#' term='google code jam'/><title type='text'>Google Code Jam 2009 1C: Bribe the Prisoners</title><content type='html'>&lt;!--
&lt;p&gt;&lt;img class="lateximg" alt="tex:x^n+y^n \not= z^n" /&gt; for all n &gt; 2?&lt;/p&gt;
lateximgc
&lt;p&gt;&lt;/p&gt;
--&gt;
&lt;p&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;br /&gt;
The &lt;a href="http://code.google.com/codejam/contest/dashboard?c=189252#s=p2"&gt;problem statement&lt;/a&gt; describes a prison with adjacent cells and a set of prisoners to be released. The problem is essentially to find the ordering of prisoners to be released such that the total number of occupied adjacent cells is minimal (and thus less coins need to be handed out).&lt;/p&gt;

&lt;p&gt;&lt;p&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;br /&gt;
Let &lt;img class="lateximg" alt="tex:\{c_1,c_2,\dots,c_Q\}" /&gt; be the set of cells in which a prisoner to be released &lt;img class="lateximg" alt="tex:p_i" /&gt; resides. Assume &lt;img class="lateximg" alt="tex:p_i" /&gt; is the optimal prisoner to be released first. The first thing we need to do is to give every prisoner left a gold coin as they all find out about &lt;img class="lateximg" alt="tex:p_i" /&gt; leaving. We are now left with two sub-arrays &lt;img class="lateximg" alt="tex:[1,\dots,c_i-1]" /&gt; and &lt;img class="lateximg" alt="tex:[c_i+1,\dots,P]" /&gt; where we need to calculate the next best prisoner to be released in each array. For the sub-array &lt;img class="lateximg" alt="tex:[1,\dots,c_i-1]" /&gt; we can iterate over the prisoners to be released residing in this range and find for each one the minimum number of coins if they were to leave and split the sub-array (making two more similar problems).&lt;/p&gt;

&lt;p&gt;Note: The minimum number of coins for a sub-array [a,b] can be memoised as the solutions to the sub-problems overlap.&lt;/p&gt;

&lt;p&gt;Here is the solution code provided by Google with a couple of additional comments:&lt;pre&gt;int p[200]; // prisoners to be released.
map&amp;lt;pair&amp;lt;int, int&amp;gt;, int&amp;gt; dp;

// Finds the minimum amount of gold needed, 
// if we only consider the cells from a to b, inclusive.
int Solve(int a, int b) {
  // First, look up the cache to see if the 
  // result is computed before.
  pair&amp;lt;int, int&amp;gt; pr(a, b);
  if(mp.find(pr) != mp.end()) return mp[pr];

  // Start the computation.
  int r = 0;
  // For each prisoner to be released in the range a&amp;lt;=p_i&amp;lt;=b
  for(int i=0; i&amp;lt;Q; i++) {
    if(p[i] &amp;gt;= a &amp;&amp; p[i] &amp;lt;= b) {
      // b-a prisoners find out about p[i] leaving and we are left with two
      // sub-arrays that need to be solved in a similar fashion.
      int tmp = (b-a) + Solve(a, p[i]-1) + Solve(p[i]+1, b);
      // Is the number of coins for the release of p[i] minimal?
      if (!r || tmp&amp;lt;r) r=tmp;
    }
  }
  mp[pr]=r;
  return r;
}
&lt;/pre&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-6199275379451429546?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/6199275379451429546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2010/03/google-code-jam-2009-1c-bribe-prisoners.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/6199275379451429546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/6199275379451429546'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2010/03/google-code-jam-2009-1c-bribe-prisoners.html' title='Google Code Jam 2009 1C: Bribe the Prisoners'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-3719326362633840291</id><published>2010-02-24T10:02:00.008Z</published><updated>2010-02-26T11:49:00.215Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='quick reference'/><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><title type='text'>Dijkstra</title><content type='html'>&lt;div class="codesection"&gt;
&lt;pre&gt;#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;limits&amp;gt;
#include &amp;lt;list&amp;gt;
#include &amp;lt;queue&amp;gt;
#include &amp;lt;vector&amp;gt;
using namespace std;

//  Implementation of Dijkstra's algorithm, using the example graph from p596 of
//  Introduction to Algorithms. As STL's priority_queue does not contain a
//  decrease-key function, the vertex is simply added multiple times and only
//  the lowest distance (first encountered on queue) is considered. Note that 
//  the number of nodes in the graph is fixed to keep code simple.

typedef pair&amp;lt;int,int&amp;gt; pii;

const int max_nodes = 5;
int distances[max_nodes];
bool visited[max_nodes];

void Dijkstra(list&amp;lt;pii&amp;gt; Adj[max_nodes], int s)
{
    for(int i=0;i&amp;lt;max_nodes;++i)
    {
        distances[i] = numeric_limits&amp;lt;int&amp;gt;::max();
        visited[i] = false;
    }
    distances[s] = 0;

    priority_queue&amp;lt;pii, vector&amp;lt;pii&amp;gt;, greater&amp;lt;pii&amp;gt; &amp;gt; Q;// pair(distance, vertex)
    Q.push(make_pair(distances[s],s));

    while(!Q.empty())
    {
        int u = Q.top().second;
        Q.pop();

        // If the vertex has been visited (by a shorter path) while it was in
        // the queue ignore it.
        if(visited[u]) continue;
        visited[u]=true;

        // Relax each adjacent vertex that hasn't already been visisted. If it
        // has been visited it will have been by a shorter path.
        for(list&amp;lt;pii&amp;gt;::iterator v=Adj[u].begin(); v != Adj[u].end(); ++v)
        {
            // If d(s,u) + d(u,v) &amp;lt; d(s,v) update d(s,v).
            if(!visited[v-&amp;gt;first] &amp;&amp; distances[v-&amp;gt;first] &amp;gt; distances[u] + v-&amp;gt;second)
            {
                distances[v-&amp;gt;first] = distances[u] + v-&amp;gt;second;
                Q.push(make_pair(distances[v-&amp;gt;first],v-&amp;gt;first));
            }
        }
    }
}

int main()
{
    list&amp;lt;pii&amp;gt; Adj[max_nodes];
    Adj[0].push_back(make_pair(1,10));    // (s,t)
    Adj[0].push_back(make_pair(3,5));    // (s,y)
    Adj[1].push_back(make_pair(2,1));    // (t,x)
    Adj[1].push_back(make_pair(3,2));    // (t,y)
    Adj[2].push_back(make_pair(4,4));    // (x,z)
    Adj[3].push_back(make_pair(1,3));    // (y,t)
    Adj[3].push_back(make_pair(2,9));    // (y,x)
    Adj[3].push_back(make_pair(4,2));    // (y,z)
    Adj[4].push_back(make_pair(0,7));    // (z,s)
    Adj[4].push_back(make_pair(2,6));    // (z,x)

    Dijkstra(Adj, 0);

    for(int i=0;i&amp;lt;max_nodes;++i)
    {
        cout &amp;lt;&amp;lt; "distances["&amp;lt;&amp;lt;i&amp;lt;&amp;lt;"] = " &amp;lt;&amp;lt; distances[i] &amp;lt;&amp;lt; ".\n";
    }
}&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-3719326362633840291?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/3719326362633840291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2010/02/dijkstra.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/3719326362633840291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/3719326362633840291'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2010/02/dijkstra.html' title='Dijkstra'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-716514379483390533</id><published>2009-12-29T12:19:00.001Z</published><updated>2009-12-29T12:20:53.672Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='maths'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='algebra'/><category scheme='http://www.blogger.com/atom/ns#' term='uni'/><title type='text'>Group theory</title><content type='html'>&lt;p&gt;This is one of the cases where I've simply got bored of solving a problem the conventional way and decided it could be a much better use of my time writing a program rather than pressing multiply on my calculator repeatedly.&lt;/p&gt;

&lt;p&gt;Here's a simple python program to find the order of an element of a group modulo some number (the binary operation being multiplication):&lt;br /&gt;
&lt;div class="codesection"&gt;
&lt;pre&gt;#!/usr/bin/env python
import sys

def element_order_mul(n,g):
    r=g
    o=1
    while r%n != 1:
        print "not",r
        r=r*g
        o=o+1
    return o

# calculates the element order under multiplication mod n.
# takes: n, element
n=int(sys.argv[1])
g=int(sys.argv[2])
o=element_order_mul(n,g)
print g,"^",o,"is congruent to 1 mod",n&lt;/pre&gt;
&lt;/div&gt;

To find the order of g=4 in the group G={1,2,4,5,7,8} with the binary operation being multiplication modulo 9:
&lt;div class="codesection"&gt;
&lt;pre&gt;[simon@simon ~]$ ./order.py 9 4
not 4
not 16
4 ^ 3 is congruent to 1 mod 9&lt;/pre&gt;
&lt;/div&gt;
Excellent!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-716514379483390533?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/716514379483390533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/12/group-theory.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/716514379483390533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/716514379483390533'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/12/group-theory.html' title='Group theory'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-8526597251456653309</id><published>2009-05-09T17:22:00.006+01:00</published><updated>2009-05-09T18:19:41.661+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maths'/><title type='text'>Trig identities</title><content type='html'>&lt;p&gt;I always have trouble remembering these, here's a simple derivation using Euler's formula:&lt;/p&gt;

&lt;p style="text-align:center;"&gt;&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\begin{align*}e^{i(A+B)} &amp;= \cos (A+B) + i \sin (A+B)\\ e^{iA}e^{iB} &amp;= (\cos A + i \sin A)(\cos B + i \sin B) \\ &amp;= \cos A \cos B + i^2 \sin A \sin B \\ &amp; \qquad + \cos A i \sin B + i \sin A \cos B. \end{align*}" /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Note that the imaginary and real parts are separate so the line &lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2} \cos A \cos B + i^2 \sin A \sin B" /&gt;, which is real, corresponds to &lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2} \cos (A+B)" /&gt; on the top line.&lt;/p&gt;

&lt;!--
Useful things:

&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}" /&gt;

--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-8526597251456653309?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/8526597251456653309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/05/trig-identities.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/8526597251456653309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/8526597251456653309'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/05/trig-identities.html' title='Trig identities'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-4252625997951156421</id><published>2009-04-17T22:43:00.012+01:00</published><updated>2009-04-17T22:56:22.133+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='terrain'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Terrain 2</title><content type='html'>&lt;p&gt;The algorithm I will implement is based on a restrictive quad tree approach.
All this means is that for each node in the tree, each of its directly adjacent 
neighbours will need to be only one LOD level different. The reason for this is
that the index buffers can be computed in advance and simply re-used
for the 16 (2^4) different cases. Each of north, east, south and west can
either be the same level or one less (if a neighbour is of a higher level then we
would be a lower level to it and hence we would join two seams of the same
detail - see figure 1).&lt;/p&gt;

&lt;div style="display:block; margin:0px auto 10px; text-align:center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_9B48Xns8Ei4/Sej4wtGzeVI/AAAAAAAAAjI/shjDrwZE7eo/s1600-h/seam.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 386px; height: 194px;" src="http://4.bp.blogspot.com/_9B48Xns8Ei4/Sej4wtGzeVI/AAAAAAAAAjI/shjDrwZE7eo/s400/seam.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5325780074991155538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:small;"&gt;Figure 1. Paint rocks&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;In regard to calculating the vertices, I'm thinking it might be a good idea
to separate the load across cores (everyone uses multicore now right?). The
general idea is to:-
&lt;ol&gt;
&lt;li&gt;Traverse the tree splitting nodes as usual.
 &lt;ol&gt;
  &lt;li&gt;Create child nodes, update 
neighbour pointers, etc. This may be recursive to keep the quadtree restricted 
to one LOD difference (note: pain, if not impossible, to parallelise).
  &lt;/li&gt;
  &lt;li&gt;Add a pointer to each node that needs its vertices calculated to a 
  list and defer actual calculation until after the tree has been 
  processed.&lt;/li&gt;
 &lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Simply dispatch calculation jobs to threads, these jobs are independent 
and nicely parallelisable.&lt;/li&gt;
&lt;li&gt;Vertex buffers also need to be created to please direct3d, shouldn't be
 too hard to squeeze them in somewhere.&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;Geomorphing is causing me to think, I can't find much on the internet to 
base my implementation from. I have never done anything to do with vertex 
interpolation before so this could be a horrible way of doing it. I'm thinking 
of sending the vertex shader: x, y, z, base_y where base_y is the value of y at 
the previous LOD level. This can be simply calculated by either taking the value
as-is (for when the point coincides with the same point in the last LOD) or 
interpolating between two values from the last LOD (i.e. where there was an edge
 on a triangle). It's then just a case of interpolating between base_y and y for each vertex using a per frame shader constant.&lt;/p&gt;

&lt;p&gt;Results soon.&lt;/p&gt;

&lt;!--
Useful things:

&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}" /&gt;

--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-4252625997951156421?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/4252625997951156421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/04/algorithm-i-will-implement-is-based-on.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/4252625997951156421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/4252625997951156421'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/04/algorithm-i-will-implement-is-based-on.html' title='Terrain 2'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9B48Xns8Ei4/Sej4wtGzeVI/AAAAAAAAAjI/shjDrwZE7eo/s72-c/seam.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-7494098025306478744</id><published>2009-04-16T11:04:00.005+01:00</published><updated>2009-04-17T22:56:33.833+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='terrain'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Terrain</title><content type='html'>&lt;p&gt;In March last year I made a terrain renderer that used noise functions to generate a reasonable looking mountain range. Since then I've learned a lot and I would like to re-visit it but this time take into account:
&lt;ul&gt;
&lt;li&gt;Normal maps&lt;/li&gt;
&lt;li&gt;Texturing&lt;/li&gt;
&lt;li&gt;Interpolation between LOD levels&lt;/li&gt;
&lt;li&gt;Decent lighting&lt;/li&gt;
&lt;li&gt;Post processing (HDR?)&lt;/li&gt;
&lt;li&gt;Lots of small optimisations&lt;/li&gt;
&lt;/ul&gt;
I would also like to give test driven design (TDD) a chance, and this seems like the perfect place to use it. I had a look at &lt;a href="http://www.boost.org/doc/libs/1_38_0/libs/test/doc/html/index.html"&gt;Boost.Test&lt;/a&gt;, being boost I trust it to be high quality. It also seems reasonably easy to use.
&lt;/p&gt;

&lt;p&gt;Here is the old terrain renderer on youtube:&lt;/p&gt;

&lt;p&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/KjRA9w_miYE&amp;hl=en&amp;fs=1&amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/KjRA9w_miYE&amp;hl=en&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;!--
Useful things:

&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}" /&gt;

--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-7494098025306478744?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/7494098025306478744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/04/terrain.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/7494098025306478744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/7494098025306478744'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/04/terrain.html' title='Terrain'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-1406932167159588090</id><published>2009-02-21T12:14:00.010Z</published><updated>2009-04-08T20:11:24.365+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maths'/><title type='text'>Quaternions</title><content type='html'>&lt;p&gt;Quaternions, discovered in 1843 by Hamilton, are the extension of complex
numbers to four dimensions. As it turns out, they are very useful in computer
graphics and can represent any rotation in 3D space in a compact and
computationally cheap form. Another advantage of quaternions is that they
avoid gimbal lock as they can describe a rotation in one operation as opposed
to Euler angles that combine yaw, pitch and roll in separate operations.&lt;/p&gt;

&lt;p&gt;A quaternion can be written as
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}=iq_x+jq_y+kq_z+q_w=\mathbf{q}_v+q_w" /&gt; where
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}i,j,k" /&gt; are all different square roots of -1 such that,
&lt;img class="lateximgc" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\begin{align*}ij &amp; = k, &amp; \qquad ji &amp; = -k, \\jk &amp; = i, &amp; kj &amp; = -i, \\ki &amp; = j, &amp; ik &amp; = -j.\end{align*}" /&gt;
The vector
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}_v" /&gt; is closely related to the axis of rotation and the angle of rotation affects all parts of the quaternion as we shall see below.
&lt;/p&gt;

&lt;p&gt;A unit quaternion,
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}" /&gt;, can represent a rotation of 
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}2\phi" /&gt; radians around an axis, 
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\mathbf{u}" /&gt;, by 
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}=(\sin \phi \mathbf{u}, \cos \phi)" /&gt;. To rotate a point or vector, 
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\mathbf{p}" /&gt;, by this quaternion is,
&lt;img class="lateximgc" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}\mathbf{p}\hat{\mathbf{q}}^{-1}." /&gt;
It can be shown that the inverse, 
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}^{-1}" /&gt;, for a unit quaternion,
&lt;img class="lateximg" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}" /&gt;, is actually the conjugate where this is defined as,
&lt;img class="lateximgc" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\hat{\mathbf{q}}^{*} = (-\mathbf{q}_v, q_w)." /&gt;
&lt;/p&gt;

&lt;p&gt;The product of two quaternions is determined by the product of the basis elements and the distributive law,
&lt;img class="lateximgc" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\begin{align*}\hat{\mathbf{q}}\hat{\mathbf{r}} &amp; = (iq_x+jq_y+kq_z+q_w)(ir_x+jr_y+kr_z+r_w)\\&amp; = i(q_y r_z-q_z r_y+r_w q_x+q_w r_x)\\&amp; \quad + j(q_z r_x-q_x r_z+r_w q_y+q_w r_y)\\&amp; \quad + k(q_x r_y-q_y r_x+r_w q_z+q_w r_z)\\&amp; \quad + q_w r_w-q_x r_x-q_y r_y-q_z r_z\\&amp; = (\mathbf{q}_v \times \mathbf{r}_v + r_w \mathbf{q}_v + q_w \mathbf{r}_v,q_w r_w - \mathbf{q}_v \cdot \mathbf{r}_v).\end{align*}" /&gt;
The transformation expressed by a unit quaternion can also, and more usefully in computer graphics, be represented by the matrix,
&lt;img class="lateximgc" alt="" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}M =\begin{pmatrix} 1-2(q_y^2+q_z^2) &amp; 2(q_xq_y-q_wq_z) &amp; 2(q_xq_z+q_wq_y) &amp; 0 \\ 2(q_xq_y+q_wq_z) &amp; 1-2(q_x^2+q_z^2) &amp; 2(q_yq_z-q_wq_x) &amp; 0 \\ 2(q_xq_z-q_wq_y) &amp; 2(q_yq_z+q_wq_x) &amp; 1-2(q_x^2+q_y^2) &amp; 0 \\ 0                &amp; 0                &amp; 0                &amp; 1 \end{pmatrix}" /&gt;
&lt;/p&gt;
&lt;p&gt;Now that's out of the way it's time for some coding.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-1406932167159588090?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/1406932167159588090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/02/quaternions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/1406932167159588090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/1406932167159588090'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/02/quaternions.html' title='Quaternions'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-1102749168985997371</id><published>2009-02-09T21:01:00.006Z</published><updated>2009-02-09T21:29:29.293Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Text rendering</title><content type='html'>&lt;p&gt;I was looking for a good library for text rendering. Something that would support truetype faces, antialiasing and kerning and be relatively easy to use. I noticed &lt;a href="http://www.freetype.org/"&gt;freetype&lt;/a&gt; in the credits to &lt;a href="http://braid-game.com/"&gt;Braid&lt;/a&gt; (which I really need to play when the PC version appears - the demo is awesome). So after a bit of research, I found it had everything I was looking for and decided to implement it in my renderer.&lt;/p&gt;
&lt;p&gt;Most of the time I spent in implementing this was actually writing the parts of the renderer I needed. I used the approach of using freetype to render a string to a texture and then rendering a quad with this texture. However, I feel uneasy about this as it makes the assumption that the strings I'm rendering don't change much (how fast is freetype at rendering?) and that it will probably take up more texture memory than storing individual glyphs as textures. This is something I'd like to investigate more but at the moment don't have the time. Anyway here's something to look at:&lt;/p&gt;
&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_9B48Xns8Ei4/SZCZLY1nznI/AAAAAAAAAio/SW75Ctnk1gg/s1600-h/the_quick_brown_fox.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://3.bp.blogspot.com/_9B48Xns8Ei4/SZCZLY1nznI/AAAAAAAAAio/SW75Ctnk1gg/s400/the_quick_brown_fox.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300905182340042354" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-1102749168985997371?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/1102749168985997371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/01/text-rendering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/1102749168985997371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/1102749168985997371'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/01/text-rendering.html' title='Text rendering'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9B48Xns8Ei4/SZCZLY1nznI/AAAAAAAAAio/SW75Ctnk1gg/s72-c/the_quick_brown_fox.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-5650775475570443552</id><published>2009-02-06T20:25:00.017Z</published><updated>2009-02-08T15:03:07.056Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Logging</title><content type='html'>&lt;p&gt;It's often useful to use logging messages or error messages in case something abnormal happens. Or just for fun. A useful trick is to send them straight to the visual studio output window. Using a small amount of code we can even override std::cout and std::cerr which is pretty cool. I'm just going to dive straight into some code:&lt;/p&gt;
&lt;div class="codesection"&gt;
&lt;pre&gt;class logbuf : public std::streambuf
{
public:
    virtual std::streamsize xsputn( const char *s, std::streamsize n )
    {
        // Output to visual studio output window
        OutputDebugStringW(widen(s).c_str());
        return n;
    }
    virtual int overflow(int c = EOF)
    {
        if(c != EOF) OutputDebugString(widen(std::string(1, c)).c_str());
        return 1;
    }
private:
    int indent_;
    char last_;
};
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="codesection"&gt;
&lt;pre&gt;
int main(int argc, const char* argv[])
{
    // Create the new stream to redirect cout and cerr output to vs.
    logbuf merr;
    std::ostream out(&amp;merr);

    // Smart class that will swap streambufs and replace them
    // when object goes out of scope.
    class StreamBuf_Swapper
    {
    public:
        StreamBuf_Swapper( std::ostream&amp; orig, std::ostream&amp; replacement )
            : buf_(orig.rdbuf()), str_(orig)
        { orig.rdbuf( replacement.rdbuf() ); }
        ~StreamBuf_Swapper() { str_.rdbuf( buf_ ); }
    private:
        std::streambuf* buf_;
        std::ostream&amp; str_;
    } cerrswap(std::cerr, out), coutswap(std::cout, out);

    try
    {
        // ... Lots of code
    }
    catch( const std::exception&amp; e )
    {
        std::cerr &lt;&lt; e.what();
    }

    return 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This code takes the streambuf associated with cout and cerr and simply swaps it with a streambuf derived class (vsstream) that prints anything to the visual studio output window. Simple and useful. One other thing to note is that if the output window contains a line formatted:&lt;/p&gt;

&lt;div class="codesection"&gt;
&lt;p&gt;&amp;lt;filename&amp;gt;(&amp;lt;line number&amp;gt;) : &amp;lt;message&amp;gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;then it will automatically display that file and line in the editor when double clicked. A few more things you could do with it would be to log errors to a file as well or maybe have something differentiate between normal log messages and error messages (in fact, I'll probably have to do this at some point).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-5650775475570443552?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/5650775475570443552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/02/logging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/5650775475570443552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/5650775475570443552'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/02/logging.html' title='Logging'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-5141156737392037595</id><published>2009-01-20T23:02:00.030Z</published><updated>2009-01-31T17:50:30.861Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='maths'/><title type='text'>Maths</title><content type='html'>&lt;p&gt;Looking around the Internet, I was a little disappointed to find that blogger doesn't natively support Latex. Fortunately there's a nifty program that you can run on a web server that will output latex code as a png.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Let &lt;img class=lateximg alt="H \leq G" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}H \leq G" /&gt; and &lt;img class=lateximg alt="x, y \in G" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}x, y \in G" /&gt;. Then either &lt;img class=lateximg alt="xH \cap yH = \emptyset" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}xH \cap yH = \emptyset" /&gt; or &lt;img class=lateximg alt="xH = yH" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}xH = yH" /&gt;.&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;p&gt;The two dimentional gradient vector for a function u(x, y) is, &lt;img class=lateximg alt="\nabla u=\left(\frac{\partial u}{\partial x},\frac{\partial u}{\partial y}\right)" src="http://www.forkosh.dreamhost.com/mathtex.cgi?\dvipng\gammacorrection{1.2}\nabla u=\left(\frac{\partial u}{\partial x},\frac{\partial u}{\partial y}\right)" /&gt;.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;All made possible thanks to &lt;a href="http://www.forkosh.com/mathtex.html"&gt;http://www.forkosh.com/mathtex.html&lt;/a&gt; - cheers!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-5141156737392037595?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/5141156737392037595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/01/maths.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/5141156737392037595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/5141156737392037595'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/01/maths.html' title='Maths'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1818931634557321641.post-7596422952016973815</id><published>2009-01-19T11:26:00.006Z</published><updated>2009-01-20T22:15:48.546Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Plans</title><content type='html'>&lt;p&gt;This journal (I hate the word blog) is going to be a place for me to organise my thoughts. I intend to list projects I'd like to do and follow them through development with regular posts showing the problems I encounter. I hope maybe it can be of use to others as well, but that is not my primary motive. Anyway, if you're actually reading this I must have done something right.&lt;/p&gt;&lt;p&gt;The list of projects I'd like to complete:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Collada loader&lt;/li&gt;
&lt;li&gt;Decent text rendering&lt;/li&gt;
&lt;li&gt;Screen space ambient occlusion (SSAO)&lt;/li&gt;
&lt;li&gt;A simple memory allocation tracker&lt;/li&gt;
&lt;li&gt;Light perspective shadow maps&lt;/li&gt;
&lt;li&gt;Self-shadowed normal mapping&lt;/li&gt;
&lt;li&gt;Rain on glass shader&lt;/li&gt;
&lt;li&gt;Efficient perlin noise generated terrain with dynamic LOD&lt;/li&gt;
&lt;li&gt;Sky dome with vertex shader to interpolate given colours
&lt;ul&gt;
 &lt;li&gt;Real time modification of shader inputs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Also my loan came through last night so I went on a shopping spree. I ended up buying:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;TH Cormen, &lt;a href="http://www.amazon.co.uk/Introduction-Algorithms-TH-Cormen/dp/0262531968/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1232148978&amp;amp;sr=1-1"&gt;Introduction to Algorithms (Paperback)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;John B. Fraleigh, &lt;a href="http://www.amazon.co.uk/First-Course-Abstract-Algebra-International/dp/0321156080/ref=pd_rhf_p_t_2"&gt;A First Course in Abstract Algebra (International Edition) (Paperback)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ian Stewart, David Tall, &lt;a href="http://www.amazon.co.uk/Complex-Analysis-Hitchhikers-Guide-Plane/dp/0521287634/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1232230066&amp;amp;sr=1-1"&gt;Complex Analysis: The Hitchhiker's Guide to the Plane (Paperback)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I'll try and do a brief review of them when I'm done reading.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1818931634557321641-7596422952016973815?l=simonhorlick.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonhorlick.blogspot.com/feeds/7596422952016973815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonhorlick.blogspot.com/2009/01/plans.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/7596422952016973815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1818931634557321641/posts/default/7596422952016973815'/><link rel='alternate' type='text/html' href='http://simonhorlick.blogspot.com/2009/01/plans.html' title='Plans'/><author><name>Simon Horlick</name><uri>http://www.blogger.com/profile/02543194724531037236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
