<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Thoughts that aren’t going anywhere.</description><title>Parentheticals &amp; Excursions</title><generator>Tumblr (3.0; @tomgibara)</generator><link>http://blog.tomgibara.com/</link><item><title>How I quickly evolved an initial concept of “an eye...</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_m4barof6X61qzfrczo1_500.png"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;How I quickly evolved an initial concept of “an eye peaking through angled brackets” into a an icon for my small &lt;a href="https://chrome.google.com/webstore/detail/gimkahfdbenbmeflimllpbjbicmlanmk"&gt;Web Intents Snooper&lt;/a&gt;  chrome app.&lt;/p&gt;

&lt;p&gt;I’m not a designer, but the tools that we all have available to us through our computers are simply incredible. So why not have a go?&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/23403159227</link><guid>http://blog.tomgibara.com/post/23403159227</guid><pubDate>Sun, 20 May 2012 09:11:48 +0100</pubDate><category>webintents</category><category>snooper</category><category>icon</category></item><item><title>My first impression of the Chrome Web Store</title><description>&lt;p&gt;I&amp;#8217;ve been interested for a long time to find out how the chrome web store stacks up against Play (aka Android market) for app developers. So, largely by way of an experiment, &lt;a href="https://chrome.google.com/webstore/detail/lkdcggjbhkaloeckehokgclkbfcpnabc"&gt;I published my harmonica tuning tool on there today&lt;/a&gt; and I thought I&amp;#8217;d capture some rambling observations in a blog post.&lt;/p&gt;

&lt;p&gt;In what follows:&lt;/p&gt;

&lt;p&gt;CWSDD = Chrome Web Store Developer Dashboard&lt;/p&gt;

&lt;p&gt;PADC = Play Android Developer Console&lt;/p&gt;

&lt;p&gt;(an aside: I&amp;#8217;m sure it&amp;#8217;s being worked on, but Google really needs to start unwinding some of the complexity that&amp;#8217;s creeping into the naming of their developer services)&lt;/p&gt;

&lt;h2&gt;Packaging&lt;/h2&gt;

&lt;p&gt;I wanted to start off with a small comment about packaging your web app for inclusion on the chrome web store: it&amp;#8217;s incredibly simple. JSON+PNG-&amp;gt;ZIP and that&amp;#8217;s it. I&amp;#8217;ve written a couple of chrome extensions for internal team use - that was super simple. This is even simpler.&lt;/p&gt;

&lt;p&gt;The CWSDD uses the Google Webmaster site ownership verification tool to safeguard against people publishing other developer&amp;#8217;s applications under their own apps. The only minor thing I tripped-up over was that using *:// requires verification of both http:// and https://.&lt;/p&gt;

&lt;h2&gt;Icon&lt;/h2&gt;

&lt;p&gt;&lt;img style="display: block; margin: auto" src="http://media.tumblr.com/tumblr_m3b7lu5eHo1qzd2hd.png"/&gt;&lt;/p&gt;

&lt;p&gt;This is a very specific tool that I doubt will garner even a small handful of users, so I&amp;#8217;ll be honest: I dashed off an icon and the minimum number of promotional images I could get away with. Even then I struggled with the icon. The guidelines specify no perspective. Is there any way to draw a harmonica without perspective that doesn&amp;#8217;t make it look like an abstract composition of shapes? Well, I politely sidestepped that guidance. It also felt odd producing just a single icon asset; I&amp;#8217;ve become accustomed to creating multiple assets for Android app icons and have come to see it as as a feature.&lt;/p&gt;

&lt;h2&gt;Promotion&lt;/h2&gt;

&lt;p&gt;The documentation for the CWSDD does an excellent job of communicating which assets you need to provide and why, and how you can expect they&amp;#8217;ll be used. I don&amp;#8217;t recall anything as clear as that for the PADC, but things may have improved considerably since I last read the docs. Of course the CWS has the advantage of not being required to support legacy clients over a wide number of form-factors, as the Android Play developers must.&lt;/p&gt;

&lt;p&gt;There were no onerous requirements. I got away with supplying just two images, a small promotional image and a screenshot (this little app isn&amp;#8217;t worth more).&lt;/p&gt;

&lt;h2&gt;Categories&lt;/h2&gt;

&lt;p&gt;There&amp;#8217;s the usual angst as you try to pigeonhole your latest wunderapp into a category. The CWSDD has a significant edge over the PADC store here since it provides for a primary and a secondary category together with developer supplied tertiary categories. How these developer specified categories are actually used is unclear though. All the guidance says is &lt;em&gt;&amp;#8220;We will use them to improve our selection of categories.&amp;#8221;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Personally I like the Google Code approach: free text labels but with the support of a large number of &amp;#8220;common labels&amp;#8221; (possibly clustered from the aggregate of those already supplied, I don&amp;#8217;t know). I do think that would provide a good basis for categorizing apps and surfacing relevant ones to users.&lt;/p&gt;

&lt;h2&gt;Publishing&lt;/h2&gt;

&lt;p&gt;In general, the process of uploading and publishing was very similar to that of publishing an Android app; both in terms of how the forms are presented and the flow that ties them together. On the whole I&amp;#8217;d say that the CWSDD feels more &amp;#8216;coherent&amp;#8217;, but that the PADC clearly packs in more features.&lt;/p&gt;

&lt;p&gt;Around publishing, the CWSDD shows up a couple of very basic deficiencies in the PADC. The first is that the CWSDD supports &amp;#8220;trusted testers&amp;#8221;. It appears to allow you to define your testers by membership of any Google Group you set up. I didn&amp;#8217;t use it (this is a bit embarrassing, but I don&amp;#8217;t actually know anyone else who&amp;#8217;d want to use this app) so I don&amp;#8217;t know how well it works in practice, but it looks like a very clever solution.&lt;/p&gt;

&lt;p&gt;Secondly, CWSDD allows you to supply a Google Analytics ID to track user views of app listing (Google Code supports this too). It&amp;#8217;s a real pity that PADC doesn&amp;#8217;t do something similar; this is valuable information that Android developers are missing out on.&lt;/p&gt;

&lt;h2&gt;Finally&lt;/h2&gt;

&lt;p&gt;These are just my first impressions of the chrome web store developer dashboard, with an application that I think has a place in the store, but which is nevertheless very a modest app. I found it simple, well documented, and quite slick.&lt;/p&gt;

&lt;p&gt;I will definitely design any future web apps with an eye to integrating them into the chrome web store and will also suggest it to relevant clients as a strong option (with the caveat that I don&amp;#8217;t know how smoothly non-free apps operate).&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/22146206878</link><guid>http://blog.tomgibara.com/post/22146206878</guid><pubDate>Mon, 30 Apr 2012 22:50:23 +0100</pubDate><category>harmonica</category><category>tuning</category><category>chrome</category><category>publish</category></item><item><title>Experimenting with Harmonica Tunings</title><description>&lt;p&gt;I&amp;#8217;ve just published a small online tool investigate different harmonica tunings.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.tomgibara.com/harmonica/tunings/"&gt;http://www.tomgibara.com/harmonica/tunings/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As indicated by my previous two posts, I&amp;#8217;ve recently become interested in learning about harmonica tunings. So I wrote a small tool that allowed me to analyze the chords that are available in a given tuning. Then I thought I&amp;#8217;d share it, so I extended it with some standard tunings and gave it just a little polish.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m35nndEdvn1qzd2hd.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Note that I&amp;#8217;ve been hasty and haven&amp;#8217;t taken any time to test it on different os/browsers/screen combinations, if anyone wants to report an issue, a comment on this post would be a good way to report it.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/21928997642</link><guid>http://blog.tomgibara.com/post/21928997642</guid><pubDate>Fri, 27 Apr 2012 21:35:09 +0100</pubDate><category>harmonica</category><category>tuning</category></item><item><title>Why an harmonica tuning?</title><description>&lt;p&gt;I&amp;#8217;ve just finished designing &lt;a href="http://blog.tomgibara.com/post/21403966341/custom-harmonica-tuning"&gt;a new harmonica tuning&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s difficult to say why. I think I just really enjoy finding elegant and balanced solutions to problems. A harmonica tuning provides a really excellent challenge - even if you&amp;#8217;re mostly musically illiterate like me.&lt;/p&gt;

&lt;p&gt;Firstly there are a number of rigid constraints: there are fixed number of holes and physical laws determine which combinations of notes they can provide.&lt;/p&gt;

&lt;p&gt;Then you have to consider the perspective of someone playing the harmonica. What patterns of notes are easy to learn? and easy to hit? and easy to express with?&lt;/p&gt;

&lt;p&gt;And then there&amp;#8217;s the music that you&amp;#8217;re trying to make it possible to play - it&amp;#8217;s accumulated over centuries and it&amp;#8217;s varied and untrammelled. You can&amp;#8217;t fit much of it into the 10 holes of a harmonica, so some hard choices need to be made.&lt;/p&gt;

&lt;p&gt;Now that I reflect on it, it&amp;#8217;s very much like producing software: there&amp;#8217;s the hard rules programming, the needs of the user to consider, and behind it all, a universe of things the user wants to achieve with your software, if you can just get it right.&lt;/p&gt;

&lt;p&gt;I love developing software, and maybe that&amp;#8217;s why I&amp;#8217;ve enjoyed designing a harmonica tuning.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/21405890999</link><guid>http://blog.tomgibara.com/post/21405890999</guid><pubDate>Fri, 20 Apr 2012 00:45:25 +0100</pubDate><category>harmonica</category><category>design</category></item><item><title>I recently started learning the harmonica. I’m rubbish at...</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_m2r1vamZ091qzfrczo1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I recently started learning the harmonica. I’m rubbish at it, but am enjoying it hugely.&lt;/p&gt;

&lt;p&gt;Mainly for the pleasure of it, I’ve taken a stab at designing my own 10 hole tuning, and I’m delighted with how well it turned out.&lt;/p&gt;

&lt;p&gt;The tuning (shown above for C) spans very nearly three octaves and I guess it would be broadly classed as a spiral tuning.&lt;/p&gt;

&lt;p&gt;The blow and draw notes on all holes are separated by a two semitones. This allows every draw note to be bent, but avoids any excessive difficultly that comes from having a larger interval (I’m thinking here of the 3 hole bends in a Richter tuning).&lt;/p&gt;

&lt;p&gt;Central to this tuning is that every seventh note in the full chromatic scale is relegated to an overblow (consequently full chromaticity requires 5 overblows). This provides a rich and useful set of chords. Indeed, drawing or blowing on any three adjacent holes always yields a major or minor chord (which consistently alternate along the harmonica).&lt;/p&gt;

&lt;p&gt;The tonic is available in the first octave on draw 1-3 (and it’s also available on blow 5-7). The dominant is adjacent on draw 3-5, with the subdominant available both major (draw 5-7) and minor (draw 2-4). I think that should make the tuning well suited to regular blues and rock.&lt;/p&gt;

&lt;p&gt;I haven’t weighed up the negatives yet, two things are evident: there are no opportunities to play octaves, and the note pattern (though systematic) is different in all three octaves - so it’s business as usual there.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/21403966341</link><guid>http://blog.tomgibara.com/post/21403966341</guid><pubDate>Fri, 20 Apr 2012 00:13:58 +0100</pubDate><category>harmonica</category><category>tuning</category></item><item><title>Binary digits</title><description>&lt;p&gt;I just realized that when I count on my fingers, I count in binary.&lt;/p&gt;

&lt;p&gt;How often as adults do we count on our fingers? Today, for the first time I can remember, I did. It was a reflex, and when I looked down at my fingers, I found myself (to my own surprise!) counting in binary patterns on my fingers.&lt;/p&gt;

&lt;p&gt;My mind was jolted back to a dim memory: that in my teens, I made a concious decision that I would count binary on my fingers. The advantage was as obvious to me then as it is now. I can count to 1024 without pausing for thought.&lt;/p&gt;

&lt;p&gt;I hope it didn&amp;#8217;t take me long to learn since, as it turns out, I clearly haven&amp;#8217;t needed the skill.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/21340065186</link><guid>http://blog.tomgibara.com/post/21340065186</guid><pubDate>Wed, 18 Apr 2012 21:55:09 +0100</pubDate><category>binary</category><category>counting</category></item><item><title>Graphics utility code</title><description>&lt;p&gt;I just committed some rough source code for, amongst other things, &lt;a href="http://blog.tomgibara.com/post/173247788/java-image-processing-code"&gt;ImageUtil&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You&amp;#8217;ll find it in my &lt;a href="http://code.google.com/p/tomgibara/source/browse/#svn%2Ftrunk%2Fgraphics%2Fgraphics-util"&gt;Google code SVN repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need this code to create &lt;a href="http://blog.tomgibara.com/post/20084214684/eye-colors"&gt;the colour charts I posted a couple of weeks ago&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s inside a Maven project, but you can probably just cherry pick this file and have things work:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tomgibara.googlecode.com/svn/trunk/graphics/graphics-util/src/main/java/com/tomgibara/graphics/util/ImageUtil.java"&gt;http://tomgibara.googlecode.com/svn/trunk/graphics/graphics-util/src/main/java/com/tomgibara/graphics/util/ImageUtil.java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And watch out for this possible issue:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4886732"&gt;http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4886732&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I haven&amp;#8217;t been able to track down all of the situations it occurs in.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/21175989374</link><guid>http://blog.tomgibara.com/post/21175989374</guid><pubDate>Sun, 15 Apr 2012 23:54:00 +0100</pubDate><category>java</category><category>code</category><category>graphics</category><category>project</category><category>Image processing</category></item><item><title>Crinch 0.7.2 Released</title><description>&lt;p&gt;Crinch has had another minor bump to version 0.7.2. This release fixes an issue that can prevent some character sequences being returned from tries.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/20965125995</link><guid>http://blog.tomgibara.com/post/20965125995</guid><pubDate>Thu, 12 Apr 2012 15:50:30 +0100</pubDate><category>crinch</category><category>0.7.2</category><category>release</category></item><item><title>Some computer generated eyes. Based this early work.</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_m2ag4vxNte1qzfrczo1_500.png"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Some computer generated eyes. Based this &lt;a href="http://blog.tomgibara.com/post/20674396666/eye-shapes"&gt;early work&lt;/a&gt;.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/20871593352</link><guid>http://blog.tomgibara.com/post/20871593352</guid><pubDate>Wed, 11 Apr 2012 01:02:55 +0100</pubDate><category>eye</category><category>genetic</category></item><item><title>Thankfully, I’m better at coding than drawing, otherwise...</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_m24q7dS1CU1qzfrczo1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Thankfully, I’m better at coding than drawing, otherwise there would be no hope.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/20674396666</link><guid>http://blog.tomgibara.com/post/20674396666</guid><pubDate>Sat, 07 Apr 2012 22:54:49 +0100</pubDate><category>eye</category><category>notebook</category></item><item><title>I made some time to try and apply what I’ve discovered...</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_m22zpk3jNh1qzfrczo1_500.png"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I made some time to try and apply &lt;a href="http://blog.tomgibara.com/post/20195637943/eye-notes"&gt;what I’ve discovered about irises&lt;/a&gt; to generating them using my genetics library. These are my very first results.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/20617438367</link><guid>http://blog.tomgibara.com/post/20617438367</guid><pubDate>Sat, 07 Apr 2012 00:24:56 +0100</pubDate><category>iris</category><category>genetic</category></item><item><title>Only the stupid</title><description>&lt;p&gt;I&amp;#8217;m writing this based on very limited information, I only know what &lt;a href="http://www.bbc.co.uk/news/uk-politics-17576745"&gt;the BBC has reported here&lt;/a&gt;. But I feel that I don&amp;#8217;t need to know more than this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A new law - which may be announced in the forthcoming Queen&amp;#8217;s Speech in May - would not allow GCHQ to access the content of emails, calls or messages without a warrant.&lt;/p&gt;
  
  &lt;p&gt;But it would enable intelligence officers to identify who an individual or group is in contact with, how often and for how long.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One can only assume, based on the repeated proposals for legislation such as this, that the government are only prohibited from installing CCTV cameras in every room of every home in the UK on the basis of cost alone.&lt;/p&gt;

&lt;p&gt;MPs who support legislation such as this must be simple minded, ignorant, or in the sway of people other than their constituents. There&amp;#8217;s no reason to believe that once such a law is enacted that it won&amp;#8217;t persist indefinitely, or even be extended. Can the present government guarantee that there will &lt;em&gt;never&lt;/em&gt; be political party elected to power that won&amp;#8217;t see advantage in abusing such breathtaking powers?&lt;/p&gt;

&lt;p&gt;McCarthyism was only 60 years ago. They are trading convenience now, for the almost certain use of the law to harass and persecute others in the future.&lt;/p&gt;

&lt;p&gt;Stupid.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/20279707790</link><guid>http://blog.tomgibara.com/post/20279707790</guid><pubDate>Sun, 01 Apr 2012 11:18:00 +0100</pubDate><category>privacy</category><category>freedom</category><category>law</category></item><item><title>Some quick notes I sketched concerning iris generation. This is...</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_m1q2tgPoTH1qzfrczo1_400.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Some quick notes I sketched concerning iris generation. This is obviously related to &lt;a href="http://blog.tomgibara.com/post/20084214684/eye-colors"&gt;yesterday’s post about eye colour&lt;/a&gt;.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/20195637943</link><guid>http://blog.tomgibara.com/post/20195637943</guid><pubDate>Sat, 31 Mar 2012 01:03:00 +0100</pubDate><category>eye</category><category>iris</category><category>notebook</category></item><item><title>Crinch 0.7.1 Released</title><description>&lt;p&gt;A quick post to say that the Crinch libraries have had a minor bump from 0.7 to 0.7.1.&lt;/p&gt;

&lt;p&gt;It was motivated by an urgent fix for a bug that impacted one of my clients. The bug was in the incomplete and undocumented &lt;em&gt;record&lt;/em&gt; library, so it shouldn&amp;#8217;t have any impact for other users of the library at the moment.&lt;/p&gt;

&lt;p&gt;The only new aspect to this release is that the source code for each library is now being put into jars and published together with a new distribution jar that aggregates all of the Crinch libraries. This jar is &lt;a href="http://code.google.com/p/tomgibara/downloads/list?q=label:crinch"&gt;available for download from Google Code&lt;/a&gt;.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/20161488491</link><guid>http://blog.tomgibara.com/post/20161488491</guid><pubDate>Fri, 30 Mar 2012 07:49:37 +0100</pubDate><category>crinch</category><category>release</category><category>0.7.1</category></item><item><title>Eye Colour Variation</title><description>&lt;p&gt;For reasons I won&amp;#8217;t elaborate on now, I want to find out how eye color can be parameterized. After some fruitless online searches, I resorted to discovering it myself.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not looking perform a scientific study, so my steps are simple: sample some eye colours, analyze them with some plots, create a model and then validate it. The first two steps haven&amp;#8217;t taken very long at all.&lt;/p&gt;

&lt;p&gt;First I used GIMP to sample average colours from 44 photographs of irises and collected them in a small swatch.&lt;/p&gt;

&lt;p&gt;&lt;img style="display:block; margin: auto" src="http://media.tumblr.com/tumblr_m1m9joCm9Z1qzd2hd.png"/&gt;&lt;/p&gt;

&lt;p&gt;Then I wrote a small Java app to plot the data. Here are the plots:&lt;/p&gt;

&lt;p&gt;&lt;img style="display:block; margin: auto" src="http://media.tumblr.com/tumblr_m1m9x9F2FM1qzd2hd.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="display:block; margin: auto" src="http://media.tumblr.com/tumblr_m1m9xgMEYk1qzd2hd.png"/&gt;&lt;/p&gt;

&lt;p&gt;The plots demonstrate that the variation of basic eye colour is actually fairly narrowly defined. This doesn&amp;#8217;t actually surprise me, but it&amp;#8217;s certainly interesting.&lt;/p&gt;

&lt;p&gt;Of course this is a small sample, but it&amp;#8217;s good enough to establish a basic approach. I think I&amp;#8217;m going to model eye colour in three separately parameterized families: blue, brown and green (no surprise there) using constraints on hue, saturation and brightness based on the plots.&lt;/p&gt;

&lt;p&gt;And just in case anyone&amp;#8217;s interested, this is the small throw-away app I wrote to create the plots. Note that it depends on &lt;a href="http://blog.tomgibara.com/post/21175989374/graphics-util-project"&gt;a class from a small Java graphics library&lt;/a&gt;&lt;/p&gt;

&lt;script src="https://gist.github.com/2231258.js"&gt; &lt;/script&gt;</description><link>http://blog.tomgibara.com/post/20084214684</link><guid>http://blog.tomgibara.com/post/20084214684</guid><pubDate>Wed, 28 Mar 2012 23:55:00 +0100</pubDate><category>eye</category><category>color</category></item><item><title>Crinch 0.7 Released</title><description>&lt;p&gt;Another weekend and another code release. I&amp;#8217;ve released a new version of my crinch libraries. It now includes &lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/package-summary.html"&gt;a documented API&lt;/a&gt; for binary coding. It currently supports a range of universal and non-universal codings. All I/O for the package is directed via the &lt;a href="http://www.tomgibara.com/projects/crinch/bits"&gt;Crinch bits library&lt;/a&gt; which makes the library very flexible.&lt;/p&gt;

&lt;h2&gt;Universal codes&lt;/h2&gt;

&lt;p&gt;The library currently supports the following universal codings.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/EliasDeltaCoding.html"&gt;Elias Delta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/EliasOmegaCoding.html"&gt;Elias Omega&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/FibonacciCoding.html"&gt;Fibonacci&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/GolombCoding.html"&gt;Golomb&lt;/a&gt; / &lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/RiceCoding.html"&gt;Rice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/UnaryCoding.html"&gt;Unary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All universal codings support arbitrarily large numbers via &lt;code&gt;BigInteger&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Non-universal codes&lt;/h2&gt;

&lt;p&gt;In addition to universal codings, the following non-universal codings are supported.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/HuffmanCoding.html"&gt;Huffman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/TruncatedBinaryCoding.html"&gt;Truncated Binary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The Huffman implementation in particular has seen lots of work: it accelerates encoding through canonicalization and block reads bits for faster decoding (without a some degree of read-ahead, I&amp;#8217;m not sure there&amp;#8217;s a faster approach). It can also return a dictionary which contains the minimal state needed to reconstruct the encoding. This can be efficiently transmitted ahead of a compressed message.&lt;/p&gt;

&lt;h2&gt;Other features&lt;/h2&gt;

&lt;p&gt;A number of helpful classes are provided in addition to the core coding implementations.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/ExtendedCoding.html"&gt;&lt;code&gt;ExtendedCoding&lt;/code&gt;&lt;/a&gt; wraps a coding to provide additional&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/CodedReader.html"&gt;&lt;code&gt;CodedReader&lt;/code&gt;&lt;/a&gt; / &lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/CodedWriter.html"&gt;&lt;code&gt;CodedWriter&lt;/code&gt;&lt;/a&gt; conveniently pairs an &lt;code&gt;ExtendedCoding&lt;/code&gt; with a &lt;code&gt;BitReader&lt;/code&gt;/&lt;code&gt;BitWriter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/CodedStreams.html"&gt;&lt;code&gt;CodedStreams&lt;/code&gt;&lt;/a&gt; provides static utility methods for common encoding and decoding tasks.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/CharFrequencyRecorder.html"&gt;&lt;code&gt;CharFrequencyRecorder&lt;/code&gt;&lt;/a&gt; accumulates character frequencies from &lt;code&gt;Strings&lt;/code&gt; and other sources of character data; useful for Huffman coding.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tomgibara.com/projects/crinch/maven/crinch-coding/apidocs/com/tomgibara/crinch/coding/CodingFrequencies.html"&gt;&lt;code&gt;CodingFrequencies&lt;/code&gt;&lt;/a&gt; calculates &amp;#8216;zero-order&amp;#8217; information entropy from data arrays.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Future extensions&lt;/h2&gt;

&lt;p&gt;The API is mostly finalized, though there are some functions which are likely to be added:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Chaining classes to allow coded readers and writers to be used with greater fluency &lt;em&gt;eg.&lt;/em&gt; &lt;code&gt;writer.chain().encodeInt(x).encodeLong(y).flush()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Implementation of more codes including possibly: range/arithmetic,  Elias gamma, exp-Golomb, Levenstein, Yamamoto&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;If anyone has an coding they want/need implemented and that isn&amp;#8217;t currently supported, you can let me know with a comment.&lt;/strong&gt;&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/19905977080</link><guid>http://blog.tomgibara.com/post/19905977080</guid><pubDate>Sun, 25 Mar 2012 19:48:41 +0100</pubDate><category>crinch</category><category>coding</category><category>release</category></item><item><title>BitWriter performance</title><description>&lt;p&gt;Crinch provides a number of different &lt;code&gt;BitWriter&lt;/code&gt; implementations that can be used to accumulate written bits in memory. They each have advantages in different situations:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ByteArrayBitWriter&lt;/strong&gt; is fairly fast, but can&amp;#8217;t be sized at a bit level.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OutputStreamBitWriter&lt;/strong&gt; can be used to write unbounded amounts of data, but is slower.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IntArrayBitWriter&lt;/strong&gt; has a fairly balanced performance profile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BitVector.openWriter&lt;/strong&gt; is flexible and faster for writes spanning many bits, but this comes with some overhead per write.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I ran a few benchmarks to verify the performance of these classes for (a) writing individual bits (b) writing multiple bits and (c) writing padding bits. I included the &lt;em&gt;&lt;code&gt;NullBitWriter&lt;/code&gt;&lt;/em&gt; to provide a baseline which gives some indication of the intrinsic API overhead.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m0yd7jkSts1qzd2hd.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;As one might expect, &lt;code&gt;BitWriter&lt;/code&gt; implementations that operate on greater numbers of bits simultaneously perform slightly worse when only single bits a written. A single ternary operator (&lt;code&gt;writeBit(bit ? 1 : 0)&lt;/code&gt; vs &lt;code&gt;write(bit, 1)&lt;/code&gt;) accounts for the significant difference in performance between &lt;code&gt;WriteBoolean&lt;/code&gt; and &lt;code&gt;WriteBit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m0ydjfVgqw1qzd2hd.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Although the &lt;code&gt;ByteArrayBitWriter&lt;/code&gt; again performs well, observe how the performance of writing to &lt;code&gt;BitVector&lt;/code&gt; improves significantly as bits are written in larger groups&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m0ydt9dTGS1qzd2hd.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;The poor performance of &lt;code&gt;IntArrayBitWriter&lt;/code&gt; for these two operations has highlighted a poorly optimized implementation. &lt;code&gt;BitVector&lt;/code&gt; maintains a &amp;#8216;flat&amp;#8217; performance profile; it provides the only writer that pads 255 bit intervals as quickly as word aligned 256 intervals.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/19374676351</link><guid>http://blog.tomgibara.com/post/19374676351</guid><pubDate>Fri, 16 Mar 2012 01:23:19 +0000</pubDate><category>crinch</category><category>performance</category><category>benchmark</category></item><item><title>All I want to do is tweak a method</title><description>&lt;p&gt;My &lt;code&gt;encodePositiveInt&lt;/code&gt; method is now going to allow calls with zero. So how should I change the method name to reflect this?&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;encodeNonNegativeInt&lt;/code&gt; long&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encodeNonNegative&lt;/code&gt; overloaded&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encodeNonNegInt&lt;/code&gt; ugly&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encodeUnsignedInt&lt;/code&gt; misleading&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encodePositiveInt&lt;/code&gt; inaccurate&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Goddamit. What do I call this method?&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/19306340782</link><guid>http://blog.tomgibara.com/post/19306340782</guid><pubDate>Wed, 14 Mar 2012 21:19:55 +0000</pubDate><category>crinch</category><category>API</category><category>design</category></item><item><title>The impact of Views on BitVector performance</title><description>&lt;p&gt;Following on from my post about &lt;a href="http://blog.tomgibara.com/post/19085882749/why-so-many-bitvector-methods"&gt;the design of the BitVector class&lt;/a&gt; yesterday, the question was asked, do you really need operations over ranges when you could just use views?&lt;/p&gt;

&lt;p&gt;For example, the following two lines of code will have exactly the same result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;v.setRange(100, 200, false);
v.rangeView(100,200).set(false);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Except that the second line will create an intermediate object. Putting aside the fact that not every environment that executes Java code has performance to match the standard Java runtime, the question of whether intermediate views should replace ranges hinges on the degree to which they impair performance.&lt;/p&gt;

&lt;h2&gt;Comparing Performance&lt;/h2&gt;

&lt;p&gt;To ascertain this, I put together a hasty benchmark this evening. It repeats a large number of different operations over a BitVector, using both ranges and views. For stable results, the fastest and slowest third of each run was discarded, and the remainder averaged for each operation.&lt;/p&gt;

&lt;p&gt;The tests were performed on a 32 bit dual core machine running&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;OpenJDK Runtime Environment (IcedTea6 1.11pre) (6b23~pre11-0ubuntu1.11.10.1)
OpenJDK Server VM (build 20.0-b11, mixed mode)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The following chart gives a summary of the results:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m0qyjrTB1L1qzd2hd.png" alt="BitVector operations performance"/&gt;&lt;/p&gt;

&lt;p&gt;It shows there is a clear and consistent cost to the object allocations (about 100ms in each of these tests). Given the performance sensitive nature of bit handling, this isn&amp;#8217;t something I&amp;#8217;d necessarily want to give away for the benefit of fewer methods.&lt;/p&gt;

&lt;h2&gt;Rotate Performance&lt;/h2&gt;

&lt;p&gt;In addition to these operations, I also measured the performance of the much slower rotate operation. This threw up an interesting anomaly: in contrast to all other operations, creating the intermediate view is always faster!&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m0qywxVSAW1qzd2hd.png" alt="BitVector rotate performance"/&gt;&lt;/p&gt;

&lt;p&gt;From the perspective of a developer who doesn&amp;#8217;t have visibility of the algorithms applied by the JIT, this is inexplicable. Here is the &lt;code&gt;rotateRange&lt;/code&gt; method which is being called:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void rotateRange(int from, int to, int distance) {
    if (from &amp;lt; 0) throw new IllegalArgumentException();
    if (from &amp;gt; to) throw new IllegalArgumentException();
    from += start;
    to += start;
    if (to &amp;gt; finish) throw new IllegalArgumentException();
    rotateAdj(from, to, distance);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the other case we are calling &lt;code&gt;rangeView()&lt;/code&gt; followed by &lt;code&gt;rotate()&lt;/code&gt;. Here is one subcall of the &lt;code&gt;rangeView&lt;/code&gt; method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public BitVector duplicate(int from, int to, boolean copy, boolean mutable) {
    if (mutable &amp;amp;&amp;amp; !copy &amp;amp;&amp;amp; !this.mutable) throw new IllegalStateException();
    if (from &amp;lt; 0) throw new IllegalArgumentException();
    if (to &amp;lt; from) throw new IllegalArgumentException();
    from += start;
    to += start;
    if (to &amp;gt; finish) throw new IllegalArgumentException();
    return duplicateAdj(from, to, copy, mutable);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice the basic similarity in structure. Both methods are doing the same checks except that the &lt;code&gt;rangeView&lt;/code&gt; method actually ends up doing more because it then needs to create a new &lt;code&gt;BitVector&lt;/code&gt;. Finally, here&amp;#8217;s the &lt;code&gt;rotate&lt;/code&gt; method that will be called on the newly created view:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void rotate(int distance) {
    rotateAdj(start, finish, distance);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These code snippets show that the the &lt;code&gt;rotateRange&lt;/code&gt; method cannot do more work than a call to &lt;code&gt;rangeView&lt;/code&gt; and &lt;code&gt;rotate&lt;/code&gt; combined. So how can it be consistently slower?&lt;/p&gt;

&lt;h2&gt;Closing Comments&lt;/h2&gt;

&lt;p&gt;I don&amp;#8217;t even have the start of explanation for this anomaly (except that it may be a bug or shortcoming in the JIT), but as I observed in &lt;a href="http://blog.tomgibara.com/post/19085882749/why-so-many-bitvector-methods#comment-462481817"&gt;my comments yesterday&lt;/a&gt;, JITs can be capricious. Writing APIs that anticipate good results from them is fine, but there&amp;#8217;s no escaping the fact that it actually passes risk onto the developers who use the library. The size of that risk is a function of performance: the degree to which JIT optimizations influence it and its importance to the developer.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/19156617386</link><guid>http://blog.tomgibara.com/post/19156617386</guid><pubDate>Mon, 12 Mar 2012 01:41:49 +0000</pubDate><category>BitVector</category><category>crinch</category><category>performance</category><category>benchmark</category><category>java</category></item><item><title>Why does BitVector have so many methods?</title><description>&lt;p&gt;This is a post about the API design of &lt;a href="http://blog.tomgibara.com/post/642433948/bitvector"&gt;BitVector&lt;/a&gt;. I don&amp;#8217;t think I&amp;#8217;ve ever written a class which carried so many methods and here I try to give some justifications.&lt;/p&gt;

&lt;p&gt;Binary data, in the form of an order sequence of bits, is an extremely fundamental software abstraction. Perhaps as a consequence of this there&amp;#8217;s frequently a lot of it, and there are often many operations that need to be perform on it.&lt;/p&gt;

&lt;p&gt;The large number of useful operations possible over binary data is one reason that BitVector has many methods, but there are others.&lt;/p&gt;

&lt;p&gt;Developers spend most of their time processing binary data as byte sequences (generally byte arrays in most languages). Grouping bits into bytes, and in more generally into longer words (such as ints and longs), has the significant benefit of improving performance. An operation on a subsequence of 64 bits could be done with a single operation on a long. Addresses are shorter too; I can&amp;#8217;t imagine any developer hankering for bit level memory addresses. And when a given word length neatly accommodates the data, everything is much simpler.&lt;/p&gt;

&lt;p&gt;But some situations arise where fixed word lengths just don&amp;#8217;t fit. Universal codes are one example: bit-length can vary dramatically from one value to the next, and though lengths are frequently less than a single byte long, they are unbounded. In this case, and in others, there isn&amp;#8217;t an easy way to avoid bit-level processing.&lt;/p&gt;

&lt;p&gt;So we&amp;#8217;re still in the situation where we might have lots of data, and lots of things to do with it, but now have the added pressure of reduced performance. Take the example of a simple loop over a byte array which sets every byte to zero. The same loop at bit level will take eight times longer. What is more, the language (Java in this case) isn&amp;#8217;t going to give you any core primitives to help: exposing direct access to byte arrays can boost efficiency, but bit-level operations are necessarily going to be forced through a method call. And, even more significantly for performance, the work of setting a single bit will also require significantly more code than the simple assignment needed for a language primitive like byte.&lt;/p&gt;

&lt;p&gt;This pressure on performance significantly changes the trade-offs made when designing a general purpose API for bit-level processing. Whereas, the value of providing a method that, say, performs an element-wise XOR between two byte arrays is questionable (given the simplicity of implementing such a method), the value of the same method at bit level is much higher because very significant optimizations become available.&lt;/p&gt;

&lt;p&gt;So performance is another reason that BitVector has so many methods. Simplistically: more specialized methods allow for more optimizations(*). But there is another reason there are so many methods.&lt;/p&gt;

&lt;p&gt;Prior to starting development of the bit package, and BitVector in particular. I reviewed my various code bases to see what I needed from such a package. What I found was that my code (which often exposed bit level data in thinly wrapped byte arrays) was frequently forced to make array copies solely to guarantee encapsulation. And additionally, bytes were being copied into other intermediate forms, and then copied back just so that certain operations could be performed by methods that didn&amp;#8217;t support the originating data representation.&lt;/p&gt;

&lt;p&gt;I realized that, by creating a single class that supported encapsulation and provided these disparate methods, I could eliminate a great deal of the copying in my applications. And when there&amp;#8217;s a lot of data, this gives a very large gain in performance.&lt;/p&gt;

&lt;p&gt;Now, as one would expect when designing a class which is becoming overloaded with methods, I investigated ways of splitting the functionality into separate classes, and superficially this appears easy - the functionality of BitVector can be split along a number of clear lines and an API looking something like this is obvious:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;v.asBits().setRange(0, 5, true);
v.asNumber().intValue();
v.asSequence().firstZero();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But a difficulty arises when BitVectors are aggregated in large numbers. For example, I had one small application that did lots of processing with 128 bit numbers. It stored a great many of these values, (representing them as a class with two long fields). For BitVector to be usable in this context, and others like it, per-instance memory usage becomes a consideration: Every &amp;#8216;sub-view&amp;#8217; of a BitVector would require one of: storage of a reference to the view in a field and references back OR creating a new view on each call OR something more complicated.&lt;/p&gt;

&lt;p&gt;I won&amp;#8217;t go into detail, but however you tackle these options, nothing very good comes out of them: memory swells, or uneven performance occurs in ways that a developer wouldn&amp;#8217;t anticipate. So I went for the low-tech approach - clear and logical method names together with documentation (&lt;a href="http://blog.tomgibara.com/post/18516125937/more-bits-of-bitvector"&gt;still ongoing&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll have to wait and see how it turns out.&lt;/p&gt;

&lt;hr&gt;&lt;p&gt;(*) I also chose to provide more generalized methods too - this decision is more questionable - and was made on the basis that there is utility in the generalized form for some applications.&lt;/p&gt;</description><link>http://blog.tomgibara.com/post/19085882749</link><guid>http://blog.tomgibara.com/post/19085882749</guid><pubDate>Sat, 10 Mar 2012 23:55:05 +0000</pubDate><category>bitvector</category><category>crinch</category><category>design</category><category>API</category><category>code</category></item></channel></rss>

