<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Data.Random</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/" />
    <link rel="self" type="application/atom+xml" href="http://axman6.homeip.net/blog/atom.xml" />
    <id>tag:axman6.homeip.net,2009-01-24:/blog//1</id>
    <updated>2009-03-19T12:07:13Z</updated>
    <subtitle>Random mutterings about life and Haskell.</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.23-en</generator>

<entry>
    <title>Data.Random visitor stats</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/03/datarandom-visitor-stats.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.33</id>

    <published>2009-03-19T02:44:09Z</published>
    <updated>2009-03-19T12:07:13Z</updated>

    <summary>I was taking a look at google analytics today, and decided to take a look at the browser percentages. I was a little surprised when I saw the results; 60.1% Firefox, 13.9% Safari, 7.9% Mozilla, 5.9% Opera, 5.5% Chrome, and 2.9% Internet Explorer, since the beginning of the year. The sort of crowd that read my blog I&apos;d expect to be using Firefox, but maybe not such a high percentage. Pretty pleased that Safari is in second, and not totally sure what Mozilla is, but probably just the other mozilla based browsers like IceWeasel. Also a little surprised with the...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Blog" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Browsers" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Software" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="browser" label="Browser" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="firefox" label="Firefox" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ie" label="IE" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="safari" label="Safari" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>I was taking a look at google analytics today, and decided to take a look at the browser percentages. I was a little surprised when I saw the results; 60.1% Firefox, 13.9% Safari, 7.9% Mozilla, 5.9% Opera, 5.5% Chrome, and 2.9% Internet Explorer, since the beginning of the year.</p>

<p>The sort of crowd that read my blog I'd expect to be using Firefox, but maybe not such a high percentage. Pretty pleased that Safari is in second, and not totally sure what Mozilla is, but probably just the other mozilla based browsers like IceWeasel. Also a little surprised with the amount of Opera users, but not too much. But the biggest surprise was IE, I never expected I'd get so few IE users, and I'm very happy about this!</p>

<p>Even though I have taken to not hacking my site so much, I'm still pleased that I can basically ignore having to even try making my site IE compatible. I know I'm likely to get some responses to this saying that I should still do it, but you know what? Screw that! if people are stupid enough to still be using IE (even if it has improved in some very good ways in recent times), then I don't care what sort of experience they have on my site. They're in the vast minority, and they annoy me, so stuff 'em.</p>

<p>Yep, not a terribly indepth or interesting post, I know, but I needed to post something... my hits were dropping!</p>

<p>'Till next time,</p>

<p>-- Axman</p>
]]>
        

    </content>
</entry>

<entry>
    <title>If you need speed, don&apos;t talk to main!</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/03/if-you-need-speed-dont-talk-to-main.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.32</id>

    <published>2009-03-04T01:23:05Z</published>
    <updated>2009-03-04T01:49:05Z</updated>

    <summary>Yesterday, I submitted my first program modification to the computer language shootout game, which is a change to the thread-ring program. If you&apos;ve followed the shootout at all, you will probably know that haskell dominates at this benchmark, with the next contender (Mozart/OZ) being 50% slower than haskell already. While i was having a look at the code, I noticed that the haskell entry was forkIO&apos;ing a lot of threads, which is exactly what we want. But we weren&apos;t quite forking enough; one of the 503 threads was the main thread. Bad idea! I learnt a few weeks ago, while...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="performance" label="Performance" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="shootout" label="Shootout" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="haskell" label="haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>Yesterday, I submitted my first program modification to the <a href="http://shootout.alioth.debian.org/">computer language shootout game</a>, which is a change to the thread-ring program. If you've followed the shootout at all, you will probably know that haskell dominates at this benchmark, with the next contender (Mozart/OZ) being 50% slower than haskell already.</p>

<p>While i was having a look at the code, I noticed that the haskell entry was forkIO'ing a lot of threads, which is exactly what we want. But we weren't quite forking enough; one of the 503 threads was the main thread. Bad idea!</p>

<p>I learnt a few weeks ago, while working on my AVar package, that communicating between bound and non bound threads (forkIO'd vs. main) when using things like MVars can be <em>really</em> slow. And this is exactly what was happening:</p>

<pre><span class='hs-definition'>main</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
  <span class='hs-varid'>a</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newMVar</span> <span class='hs-varop'>.</span> <span class='hs-varid'>read</span> <span class='hs-varop'>.</span> <span class='hs-varid'>head</span> <span class='hs-varop'>=&lt;&lt;</span> <span class='hs-varid'>getArgs</span>
  <span class='hs-varid'>z</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>foldM</span> <span class='hs-varid'>new</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>[</span><span class='hs-num'>2</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>ring</span><span class='hs-keyglyph'>]</span>
  <span class='hs-varid'>thread</span> <span class='hs-num'>1</span> <span class='hs-varid'>z</span> <span class='hs-varid'>a</span></pre>

<p>as you can see, the last/first thread was being run in main, so once per loop around the ring, we were talking to main via an MVar, and then talking to another forkIO'd thread via another MVar. So here's what I did:</p>

<pre><span class='hs-definition'>main</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
  <span class='hs-varid'>a</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newMVar</span> <span class='hs-varop'>.</span> <span class='hs-varid'>read</span> <span class='hs-varop'>.</span> <span class='hs-varid'>head</span> <span class='hs-varop'>=&lt;&lt;</span> <span class='hs-varid'>getArgs</span>
  <span class='hs-varid'>z</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>foldM</span> <span class='hs-varid'>new</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>[</span><span class='hs-num'>2</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>ring</span><span class='hs-keyglyph'>]</span>
  <span class='hs-varid'>ret</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newEmptyMVar</span>
  <span class='hs-varid'>forkIO</span> <span class='hs-layout'>(</span><span class='hs-varid'>thread</span> <span class='hs-num'>1</span> <span class='hs-varid'>z</span> <span class='hs-varid'>a</span> <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-varid'>putMVar</span> <span class='hs-varid'>ret</span><span class='hs-layout'>)</span>
  <span class='hs-varid'>takeMVar</span> <span class='hs-varid'>ret</span></pre>

<p>Two and a half lines of code. What were the results? Well, when the program was run with n = 50,000,000, the original ran in ~14.2s, with -N{1,2,3,4}, my modified one took on average ~9.3s, which is about a 33% improvement. It should be noted that when both programs are compiled without -threaded, there is almost no difference in speed at all (and they both run considerably faster than the non threaded version). Need to talk to the shootout peeps and find out if it's against the rules to compile without -threaded, and get an even more massive speed boost.</p>

<p>-- Axman</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Back at uni</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/back-at-uni.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.31</id>

    <published>2009-02-27T08:27:53Z</published>
    <updated>2009-02-27T08:54:43Z</updated>

    <summary>It&apos;s Friday night, and I have just finished my first week of my second year at the Australian National University. This is the reason I haven&apos;t written anything here for the last week, and my blog rate will probably remain low for the next 10 weeks... but I&apos;ll do my best! This semester I&apos;m doing some rather interesting courses (and some not so much...) COMP2300 - Introduction to Computer Systems Which is about.. well computer systems. It covers topics like binary representations of numbers, C, computer architecture, etc. The thing I am however most looking forward to the most will...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="News" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Uni" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="uni" label="uni" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>It's Friday night, and I have just finished my first week of my second year at the Australian National University. This is the reason I haven't written anything here for the last week, and my blog rate will probably remain low for the next 10 weeks... but I'll do my best!</p>

<p>This semester I'm doing some rather interesting courses (and some not so much...)</p>

<ul>
<li><p><a href="http://cs.anu.edu.au/student/comp2300/">COMP2300</a> - <strong>Introduction to Computer Systems</strong></p>

<p>Which is about.. well computer systems. It covers topics like binary representations of numbers, C, computer architecture, etc. The thing I am however most looking forward to the most will be the third assignment, which will be based around the uni's new T2 (the one <a href="http://ghcsparc.blogspot.com/">Ben Lippmeier</a> is using for most of his GHC on SPARC work)</p></li>
<li><p><a href="http://cs.anu.edu.au/student/comp2100/">COMP2100</a> - <strong>Software Construction</strong></p>

<p>This seems to be more about how to write larger software, than actual programming (though it does emphasise programming weekly to get into good habits). I'm interested to see for the <em>Personal Software Process</em> (PSP) stuff goes, it seems to me that it can make you a more productive programmer quite easily. After only an hour of using the time keeping for it, i've noticed i don't get distracted as much, because it's not programming time, so all i do is program in this time. Means i distract myself less, which is very helpful.</p></li>
<li><p>ENGN2211 - <strong>Electronic Circuits</strong></p>

<p>This is a second year electronics course, and should be fairly interesting too. Not much to say about this one...</p></li>
<li><p>ENGN2226 - <strong>Engineering Systems Analysis</strong></p>

<p>This course is taught by a pretty cool German maths PhD, and focuses mostly on modelling systems, which is obviously an integral part of engineering. We'll have to use MATLAB for this, which from what I've heard from others may not be very fu at all. Could be a good place to use some of the nice statistical packages for haskell...</p></li>
</ul>

<p>Anyway, I'll try and keep up with the haskelling, but I'll be doing a lot of non haskell this semester (C, Java, ASM, MATLAB), so it may have to fall by the way side for now :(</p>

<p>-- Axman</p>
]]>
        

    </content>
</entry>

<entry>
    <title>AVar changes</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/avar-changes.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.30</id>

    <published>2009-02-22T02:10:27Z</published>
    <updated>2009-02-22T02:23:41Z</updated>

    <summary>So what&apos;s new? Well, i split it up a bit, into three modules: Data.AVar, the classic interface, Data.AVar.Unsafe, the same as Data.AVar, but it throws any exceptions encountered by the variable, instead of passing them back to the user, and Data.AVar.Internal, which contains the code for the actual for AVars, and the datatypes used by them...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
    <category term="avar" label="AVar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="concurrent" label="Concurrent" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>Yesterday, i stuck AVar 0.0.4 on hackage. Again, not thinking things through as well ad i should have, i realised later it should have been the 0.1.0 release, since it was the first major change to the package since i first wrote it.</p>

<p>So what's new? Well, i split it up a bit, into three modules: Data.AVar, the classic interface, Data.AVar.Unsafe, the same as Data.AVar, but it throws any exceptions encountered by the variable, instead of passing them back to the user, and Data.AVar.Internal, which contains the code for the actual for AVars, and the datatypes used by them.</p>

<p>I think this is a nice way of doing things, and hopefully will make using the system a little easier if you don't expect to cause exceptions.</p>

<p>So as always, if you have any suggestions, please let me know.</p>

<p>-- Axman</p>
]]>
        

    </content>
</entry>

<entry>
    <title>AVar released (three times)</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/avar-released.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.29</id>

    <published>2009-02-20T08:40:45Z</published>
    <updated>2009-02-20T08:57:34Z</updated>

    <summary>The other day, I put my AVar package on hackage. Doing so taught me more than i expected it would, mainly that i need to do more testing of cabal packages before submitting them, and also to make sure you&apos;ve exported all the functions you need to actually use the package (I forgot to put putAVar in the module exports -_-). So i&apos;m up to release 0.0.3, without much work being done at all (although, I can&apos;t think of much more to do really). With the current release, i think that all exceptions that may occur from functions passed by...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Software" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="concurrent" label="Concurrent" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="hackage" label="hackage" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="haskell" label="haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>The other day, I put my AVar package on hackage. Doing so taught me more than i expected it would, mainly that i need to do more testing of cabal packages before submitting them, and also to make sure you've exported all the functions you need to actually use the package (I forgot to put putAVar in the module exports -_-). So i'm up to release 0.0.3, without much work being done at all (although, I can't think of much more to do really).</p>

<p>With the current release, i think that all exceptions that may occur from functions passed by the user to the variable should be caught by and handled correctly by the variable. I guess in a sense, AVars are smart variables that know what is and isn't good for them, and will refuse to hurt themselves (hopefully!). </p>

<p>If you're interested in seeing what AVar can do, check out the <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/AVar">Hackage page</a>. I really have no idea how it might be useful, but I'd love to hear others thoughts on it. </p>

<p>If you have any requests, please let me know, and I'll see what I can do (proper transactional ... transactions are not something I want to tackle, especially with uni starting on monday)</p>
]]>
        

    </content>
</entry>

<entry>
    <title>ASTM updates</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/astm-updates.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.28</id>

    <published>2009-02-17T12:15:00Z</published>
    <updated>2009-02-17T14:21:50Z</updated>

    <summary>Today, I&apos;ve been talking with some people in #haskell about this ASTM thing, and I&apos;ve had some great input, mainly from Stefan Ljungstrand (ski on #haskell), along with quicksilver and Simon Marlow, and I thought I&apos;d share the changes I&apos;ve put in with their help. I&apos;m still not sure how useful this stuff is, but it&apos;s fun and I&apos;m learning. If you&apos;re wondering what i&apos;m on about, see this post. So, the new features I&apos;ve added are mainly to do with exception handling, so that variables don&apos;t &apos;die&apos; if you call tail on [], they report the error, and don&apos;t...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="concurrent" label="Concurrent" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="exceptions" label="Exceptions" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="stm" label="STM" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>Today, I've been talking with some people in #haskell about this ASTM thing, and I've had some great input, mainly from Stefan Ljungstrand (ski on #haskell), along with quicksilver and Simon Marlow, and I thought I'd share the changes I've put in with their help. I'm still not sure how useful this stuff is, but it's fun and I'm learning. If you're wondering what i'm on about, see <a href="http://axman6.homeip.net/blog/2009/02/astm-redundant-stmish-fun.html">this post</a>.</p>

<p>So, the new features I've added are mainly to do with exception handling, so that variables don't 'die' if you call tail on [], they report the error, and don't change the 'state'. I've also deleted the Swap constructor, and replaced it with a more general Mod' constructor:</p>

<pre><span class='hs-keyword'>data</span> <span class='hs-conid'>Transaction</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span>
      <span class='hs-conid'>Put</span> <span class='hs-varid'>a</span>
    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Get</span> <span class='hs-layout'>(</span><span class='hs-conid'>MVar</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Mod</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>MVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>E</span><span class='hs-varop'>.</span><span class='hs-conid'>SomeException</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
    <span class='hs-keyglyph'>|</span> <span class='hs-keyword'>forall</span> <span class='hs-varid'>b</span><span class='hs-varop'>.</span> <span class='hs-conid'>Mod'</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>MVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>Either</span> <span class='hs-conid'>E</span><span class='hs-varop'>.</span><span class='hs-conid'>SomeException</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Atom</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>MVar</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span></pre>

<p>This you provide a function which takes the current 'state', possibly modifies it, and returns something else, and return that something else back to you. This works a lot like the State monad, but allows concurrency. </p>

<p>I've changed handler as well to look like this:</p>

<pre><span class='hs-definition'>handler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Chan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Transaction</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>b</span> 
<span class='hs-definition'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varop'>!</span><span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
  <span class='hs-varid'>req</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readChan</span> <span class='hs-varid'>chan</span>
  <span class='hs-keyword'>case</span> <span class='hs-varid'>req</span> <span class='hs-keyword'>of</span>
    <span class='hs-conid'>Put</span> <span class='hs-varid'>a</span>         <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>a</span>
    <span class='hs-conid'>Get</span> <span class='hs-varid'>mvar</span>      <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
        <span class='hs-varid'>putMVar</span> <span class='hs-varid'>mvar</span> <span class='hs-varid'>x</span>
        <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span>

    <span class='hs-conid'>Mod</span> <span class='hs-varid'>f</span> <span class='hs-varid'>mvar</span>    <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
        <span class='hs-keyword'>let</span> <span class='hs-varid'>x'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>f</span> <span class='hs-varid'>x</span>
        <span class='hs-varid'>p</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>E</span><span class='hs-varop'>.</span><span class='hs-varid'>catch</span> <span class='hs-layout'>(</span><span class='hs-conid'>E</span><span class='hs-varop'>.</span><span class='hs-varid'>evaluate</span> <span class='hs-varid'>x'</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span><span class='hs-layout'>)</span>
                     <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>e</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
        <span class='hs-varid'>putMVar</span> <span class='hs-varid'>mvar</span> <span class='hs-varid'>p</span>
        <span class='hs-keyword'>case</span> <span class='hs-varid'>p</span> <span class='hs-keyword'>of</span>
          <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x'</span>
          <span class='hs-keyword'>_</span>       <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span>

    <span class='hs-conid'>Mod'</span> <span class='hs-varid'>f</span> <span class='hs-varid'>mvar</span>    <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
          <span class='hs-keyword'>let</span> <span class='hs-varid'>y</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>f</span> <span class='hs-varid'>x</span>
          <span class='hs-varid'>p</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>E</span><span class='hs-varop'>.</span><span class='hs-varid'>try</span> <span class='hs-layout'>(</span><span class='hs-conid'>E</span><span class='hs-varop'>.</span><span class='hs-varid'>evaluate</span> <span class='hs-varid'>a</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-conid'>E</span><span class='hs-varop'>.</span><span class='hs-varid'>evaluate</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span>
          <span class='hs-keyword'>case</span> <span class='hs-varid'>p</span> <span class='hs-keyword'>of</span>
              <span class='hs-conid'>Right</span> <span class='hs-keyword'>_</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
                  <span class='hs-varid'>putMVar</span> <span class='hs-varid'>mvar</span> <span class='hs-layout'>(</span><span class='hs-conid'>Right</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span>
                  <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>a</span>
              <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
                  <span class='hs-varid'>putMVar</span> <span class='hs-varid'>mvar</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
                  <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span>

    <span class='hs-conid'>Atom</span> <span class='hs-varid'>test</span> <span class='hs-varid'>y</span> <span class='hs-varid'>n</span> <span class='hs-varid'>res</span> <span class='hs-keyglyph'>-&gt;</span>
      <span class='hs-keyword'>if</span> <span class='hs-varid'>test</span> <span class='hs-varid'>x</span>
        <span class='hs-keyword'>then</span> <span class='hs-keyword'>do</span>
              <span class='hs-varid'>putMVar</span> <span class='hs-varid'>res</span> <span class='hs-conid'>True</span>
              <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
              <span class='hs-varid'>putMVar</span> <span class='hs-varid'>res</span> <span class='hs-conid'>False</span>
              <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
    </pre>

<p>As you can see, I've added some exception handling, but I still need to add some more to the Atom/condModAVar case. What I want is something that can keep running even after there's been an exception. I mean, who wants a mutable variable to just stop working huh?. I think once I get that done, along with haddock docs, I'll stick it on hackage.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>ASTM: redundant STMish fun</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/astm-redundant-stmish-fun.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.27</id>

    <published>2009-02-16T16:20:18Z</published>
    <updated>2009-02-16T16:47:20Z</updated>

    <summary>...an idea for the emulation of mutable variables, using functions as a way of storing the values in an accumulating parameter of sorts. They could safely be shared between threads, and could (and sort of do) support atomic actions...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="concurrent" label="Concurrent" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="stm" label="STM" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>So, tonight, I had an idea for something that I'm not sure if it's either useful, efficient, interesting or anything other than a waste of time. It was an idea for the emulation of mutable variables, using functions as a way of storing the values in an accumulating parameter of sorts. They could safely be shared between threads, and could (and sort of do) support atomic actions.</p>

<p>It turned out to be really simple to implement, and I think just showing you the code would explain what I'm on about more than anything else. I don't know how else this could be extended (I'm sure it could be though, for some fairly interesting ideas), and since it has been written in the wee hours of the morning, I may be doing some pretty stupid stuff...</p>

<p>So, I'd love to hear some discussion (though yes, I do already know this could probably be done with MVars or TVars or what have you) and ideas, and here's the code:</p>

<pre><span class='hs-keyword'>module</span> <span class='hs-conid'>ASTM</span> <span class='hs-keyword'>where</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span><span class='hs-varop'>.</span><span class='hs-conid'>MVar</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span><span class='hs-varop'>.</span><span class='hs-conid'>Chan</span>

<span class='hs-keyword'>data</span> <span class='hs-conid'>Transaction</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span>
      <span class='hs-conid'>Put</span> <span class='hs-varid'>a</span>
    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Get</span> <span class='hs-layout'>(</span><span class='hs-conid'>MVar</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Mod</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
    <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Atom</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>MVar</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span>

<span class='hs-keyword'>data</span> <span class='hs-conid'>AVar</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>Chan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Transaction</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 

<span class='hs-definition'>newAVar</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>AVar</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<span class='hs-definition'>newAVar</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>chan</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Chan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Transaction</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>forkIO</span> <span class='hs-layout'>(</span><span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>AVar</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span>
  <span class='hs-keyword'>where</span>
      <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
          <span class='hs-varid'>req</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readChan</span> <span class='hs-varid'>chan</span>
          <span class='hs-keyword'>case</span> <span class='hs-varid'>req</span> <span class='hs-keyword'>of</span>
              <span class='hs-conid'>Put</span> <span class='hs-varid'>a</span>         <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>a</span>
              <span class='hs-conid'>Get</span> <span class='hs-varid'>mvar</span>      <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
                  <span class='hs-varid'>putMVar</span> <span class='hs-varid'>mvar</span> <span class='hs-varid'>x</span>
                  <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span>
              <span class='hs-conid'>Mod</span> <span class='hs-varid'>f</span>         <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
              <span class='hs-conid'>Atom</span> <span class='hs-varid'>test</span> <span class='hs-varid'>y</span> <span class='hs-varid'>n</span> <span class='hs-varid'>res</span> <span class='hs-keyglyph'>-&gt;</span>
                <span class='hs-keyword'>if</span> <span class='hs-varid'>test</span> <span class='hs-varid'>x</span>
                  <span class='hs-keyword'>then</span> <span class='hs-keyword'>do</span>
                        <span class='hs-varid'>putMVar</span> <span class='hs-varid'>res</span> <span class='hs-conid'>True</span>
                        <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
                  <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
                        <span class='hs-varid'>putMVar</span> <span class='hs-varid'>res</span> <span class='hs-conid'>False</span>
                        <span class='hs-varid'>handler</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>

<span class='hs-definition'>putAVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>AVar</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>writeChan</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Put</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
<span class='hs-definition'>modAVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>AVar</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>writeChan</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Mod</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span>
<span class='hs-definition'>getAVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>AVar</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span>   <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>res</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newEmptyMVar</span>
    <span class='hs-varid'>writeChan</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Get</span> <span class='hs-varid'>res</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>takeMVar</span> <span class='hs-varid'>res</span>
<span class='hs-definition'>condModAVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>AVar</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-varid'>p</span> <span class='hs-varid'>t</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>res</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newEmptyMVar</span>
    <span class='hs-varid'>writeChan</span> <span class='hs-varid'>chan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Atom</span> <span class='hs-varid'>p</span> <span class='hs-varid'>t</span> <span class='hs-varid'>f</span> <span class='hs-varid'>res</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>takeMVar</span> <span class='hs-varid'>res</span>
</pre>
]]>
        

    </content>
</entry>

<entry>
    <title>Shootout PiDigits program kinda sucks (and possibly so does GHC)</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/shootout-pidigits-program-kinda-sucks-and-possibly-so-does-ghc.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.26</id>

    <published>2009-02-11T13:14:38Z</published>
    <updated>2009-02-11T13:59:06Z</updated>

    <summary>So, I&apos;m putting a call out to see if anyone else can either think of a better way to get the answer than the current entry, or any tips about reducing memory usage. If you come up with anything, I&apos;d love to hear from you.</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Software" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ghc" label="GHC" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="performance" label="Performance" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="haskell" label="haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>So I've been trying to see if I could speed up the <a href="http://shootout.alioth.debian.org/u64q/benchmark.php?test=pidigits&amp;lang=all">pidigits</a> program, and, well, failed. I'm not alone though, Stephen Blackheath and others have tried too, and no one's managed to make things much, if at all faster.</p>

<p>The main problem seems to be that GHC is allocating <strong>a lot</strong> of RAM, which must be related to the need for Integers. The current program uses up 500+MB by the time it finishes. Not good.</p>

<p>So, I'm putting a call out to see if anyone else can either think of a better way to get the answer than the current entry, or any tips about reducing memory usage. If you come up with anything, I'd love to hear from you.</p>

<p>Cheers,
~ Axman</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Other shootout news</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/other-shootout-news.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.24</id>

    <published>2009-02-05T12:44:56Z</published>
    <updated>2009-02-05T13:15:57Z</updated>

    <summary>I&apos;ve been talking to Stephen Blackheath on the #haskell-in-depth channel, and he&apos;s just submitted another new program to the shootout. This entry is for the regex-dna problem. For this benchmark, each language is limited by the speed of the regex library it&apos;s using. Right... let me see. Here&apos;s what I did; I am not certain, but it seems that forcing the evaluation of s1, s2 and s3 (the blobs of input data) before parallelizing the processing gave better CPU utilisation. I also changed the part at the end where it does large numbers of pattern substitutions, so that it updated...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Software" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="shootout" label="Shootout" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>I've been talking to Stephen Blackheath on the #haskell-in-depth channel, and he's just submitted another new program to the shootout. This entry is for the <a href="http://shootout.alioth.debian.org/u64q/benchmark.php?test=regexdna&amp;lang=all">regex-dna</a> problem. </p>

<blockquote>
  <p>For this benchmark, each language is limited by the speed of the regex library it's using. <br />
  Right... let me see.  Here's what I did; <br />
  I am not certain, but it seems that forcing the evaluation of s1, s2 and s3 (the blobs of input data) before parallelizing the processing
  gave better CPU utilisation.
  I also changed the part at the end where it does large numbers of pattern substitutions, so that it updated everything in-place in a mutable buffer.
   I found that splitting the pattern substitutions into chunks sped things up by a factor of three. It looks like there's some sort of overhead incurred on large buffers when the regex 'match' function creates its AllMatches array. <br />
  The reason why I needed memmove instead of memcpy is that memmove can work on overlapping buffers. <br />
  These changes improved the performance from 1:00 user / 0:42.2 real to 0:40.1 user / 0:25.12 real on my dual core, compared with 23.3 sec user for the slower non-parallel one of the two C++ implementations.  (The parallel one wouldn't build for me.)</p>
</blockquote>

<p>You can see the details of the submission <a href="https://alioth.debian.org/tracker/index.php?func=detail&amp;aid=311443&amp;group_id=30402&amp;atid=411646">here</a>, and the <a href="https://alioth.debian.org/tracker/download.php/30402/411646/311443/3056/regex.hs">actual code</a>. He also adds:</p>

<blockquote>
  <p>I took my unsafePerformIO's out too.  I have a reputation to maintain!</p>
</blockquote>

<p>It's good to see that someone else is working on making haskell look good (and doing a much better job than me thankfully!). Maybe soon we'll be topping the list, or at least beating Java to move up to 4th place.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>More n-bodies speedups</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/more-n-bodies-speedups.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.23</id>

    <published>2009-02-04T14:11:08Z</published>
    <updated>2009-02-04T14:36:02Z</updated>

    <summary>So I&apos;ve been taking full advantage of the new #haskell-in-depth channel, and with the thanks of blackh and others, I&apos;ve made a few more changes, and I&apos;ve shaved another whole 30 seconds of my already not too shabby 1m17s. I&apos;m now down to 47.215s, making a saving of 30s, or a saving of 39%. If you&apos;re wondering what I&apos;m on about, take a look at this post for the story of my n-bodies program so far, and this port for what my code looked like before. So how did I do it this time? Well, I decided STRefs weren&apos;t necessary,...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Software" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="shootout" label="Shootout" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>So I've been taking full advantage of the new #haskell-in-depth channel, and with the thanks of blackh and others, I've made a few more changes, and I've shaved another whole 30 seconds of my already not too shabby 1m17s. I'm now down to 47.215s, making a saving of 30s, or a saving of 39%.</p>

<p>If you're wondering what I'm on about, take a look at <a href="http://axman6.homeip.net/blog/2009/02/n-bodies-evolution.html">this post</a> for the story of my n-bodies program so far, and <a href="http://axman6.homeip.net/blog/2009/02/n-bodies-speedup-50.html">this port</a> for what my code looked like before.</p>

<p>So how did I do it this time? Well, I decided STRefs weren't necessary, and could easily be replaces with accumulating parameters in basically all of my code that used them. I did this in the hope they would be kept in registers, but even if they're not, it's still faster. I also saved about 3 seconds by inlining all my read* and write* functions with {-# INLINE #-} pragmas that would write or fetch the various parts of the Body's info. So here's the code, first the original one:</p>

<pre><span class='definition'>advance</span> <span class='varid'>dt</span> <span class='varid'>ps</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
    <span class='varid'>forM_</span> <span class='varid'>index1</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>i</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
        <span class='comment'>-- (B p v m) &lt;- readBody ps i</span>
        <span class='varid'>p</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readPos</span> <span class='varid'>ps</span> <span class='varid'>i</span>
        <span class='varid'>v</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readVel</span> <span class='varid'>ps</span> <span class='varid'>i</span>
        <span class='varid'>m</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readMass</span> <span class='varid'>ps</span> <span class='varid'>i</span>
        <span class='varid'>vvar</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>newSTRef</span> <span class='varid'>v</span>

        <span class='varid'>forM_</span> <span class='layout'>(</span><span class='varid'>index2</span> <span class='varid'>i</span><span class='layout'>)</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>j</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
            <span class='comment'>-- (B p' v' m') &lt;- readBody ps j</span>
            <span class='varid'>p'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readPos</span> <span class='varid'>ps</span> <span class='varid'>j</span>
            <span class='varid'>v'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readVel</span> <span class='varid'>ps</span> <span class='varid'>j</span>
            <span class='varid'>m'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readMass</span> <span class='varid'>ps</span> <span class='varid'>j</span>
            <span class='keyword'>let</span> <span class='varid'>dp</span> <span class='keyglyph'>=</span> <span class='varid'>p</span> <span class='varop'>.-.</span> <span class='varid'>p'</span>
                <span class='varid'>dst</span> <span class='keyglyph'>=</span> <span class='varid'>mag</span> <span class='varid'>dp</span>
                <span class='varid'>magnit</span> <span class='keyglyph'>=</span> <span class='varid'>dt</span> <span class='varop'>/</span> <span class='layout'>(</span><span class='varid'>dst</span> <span class='varop'>*</span> <span class='varid'>dst</span> <span class='varop'>*</span> <span class='varid'>dst</span><span class='layout'>)</span>
                <span class='varid'>change</span> <span class='keyglyph'>=</span> <span class='varid'>magnit</span> <span class='varop'>*.</span> <span class='varid'>dp</span>
                <span class='layout'>(</span><span class='varid'>sca1</span><span class='layout'>,</span><span class='varid'>sca2</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='layout'>(</span><span class='varid'>m'</span> <span class='varop'>*.</span> <span class='varid'>change</span><span class='layout'>,</span> <span class='varid'>m</span> <span class='varop'>*.</span> <span class='varid'>change</span><span class='layout'>)</span>
            <span class='varid'>writeVel</span> <span class='varid'>ps</span> <span class='varid'>j</span> <span class='layout'>(</span><span class='varid'>v'</span> <span class='varop'>.+.</span> <span class='varid'>sca2</span><span class='layout'>)</span>
            <span class='varid'>modifySTRef</span> <span class='varid'>vvar</span> <span class='layout'>(</span><span class='varop'>.-.</span> <span class='varid'>sca1</span><span class='layout'>)</span>
        <span class='varid'>vvar'</span><span class='keyglyph'>@</span><span class='layout'>(</span><span class='conid'>V</span> <span class='varid'>nx</span> <span class='varid'>ny</span> <span class='varid'>nz</span><span class='layout'>)</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readSTRef</span> <span class='varid'>vvar</span>
        <span class='comment'>-- unsafeIOToST (print vvar')</span>
        <span class='varid'>writeVel'</span> <span class='varid'>ps</span> <span class='varid'>i</span> <span class='varid'>nx</span> <span class='varid'>ny</span> <span class='varid'>nz</span>
        <span class='varid'>writePos</span> <span class='varid'>ps</span> <span class='varid'>i</span> <span class='varop'>$</span> <span class='varid'>move'</span> <span class='varid'>dt</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p</span> <span class='varid'>vvar'</span> <span class='varid'>m</span><span class='layout'>)</span>
</pre>

<p>And the new one, with an inner loop:</p>

<pre><span class='definition'>advance</span> <span class='varid'>dt</span> <span class='varid'>ps</span> <span class='keyglyph'>=</span>
    <span class='varid'>forM_</span> <span class='varid'>index1</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>i</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
        <span class='comment'>-- (B p v m) &lt;- readBody ps i</span>
        <span class='varid'>p</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readPos</span> <span class='varid'>ps</span> <span class='varid'>i</span>
        <span class='varid'>v</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readVel</span> <span class='varid'>ps</span> <span class='varid'>i</span>
        <span class='varid'>m</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readMass</span> <span class='varid'>ps</span> <span class='varid'>i</span>
        <span class='keyword'>let</span> <span class='varid'>loop2</span> <span class='varop'>!</span><span class='varid'>j</span> <span class='varop'>!</span><span class='varid'>v</span><span class='keyglyph'>@</span><span class='layout'>(</span><span class='conid'>V</span> <span class='varop'>!</span><span class='varid'>x</span> <span class='varop'>!</span><span class='varid'>y</span> <span class='varop'>!</span><span class='varid'>z</span><span class='layout'>)</span> 
                <span class='keyglyph'>|</span> <span class='varid'>j</span> <span class='varop'>&gt;</span> <span class='varid'>numPs</span> <span class='keyglyph'>=</span> <span class='varid'>return</span> <span class='varid'>v</span>
                <span class='keyglyph'>|</span> <span class='varid'>otherwise</span>  <span class='keyglyph'>=</span> <span class='keyword'>do</span>
                   <span class='varid'>p'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readPos</span> <span class='varid'>ps</span> <span class='varid'>j</span>
                   <span class='varid'>v'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readVel</span> <span class='varid'>ps</span> <span class='varid'>j</span>
                   <span class='varid'>m'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readMass</span> <span class='varid'>ps</span> <span class='varid'>j</span>
                   <span class='keyword'>let</span> <span class='varid'>dp</span> <span class='keyglyph'>=</span> <span class='varid'>p</span> <span class='varop'>.-.</span> <span class='varid'>p'</span>
                       <span class='varid'>dst</span> <span class='keyglyph'>=</span> <span class='varid'>mag</span> <span class='varid'>dp</span>
                       <span class='varid'>magnit</span> <span class='keyglyph'>=</span> <span class='varid'>dt</span> <span class='varop'>/</span> <span class='layout'>(</span><span class='varid'>dst</span> <span class='varop'>*</span> <span class='varid'>dst</span> <span class='varop'>*</span> <span class='varid'>dst</span><span class='layout'>)</span>
                       <span class='varid'>change</span> <span class='keyglyph'>=</span> <span class='varid'>magnit</span> <span class='varop'>*.</span> <span class='varid'>dp</span>
                       <span class='layout'>(</span><span class='varid'>sca1</span><span class='layout'>,</span><span class='varid'>sca2</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='layout'>(</span><span class='varid'>m'</span> <span class='varop'>*.</span> <span class='varid'>change</span><span class='layout'>,</span> <span class='varid'>m</span> <span class='varop'>*.</span> <span class='varid'>change</span><span class='layout'>)</span>
                   <span class='varid'>writeVel</span> <span class='varid'>ps</span> <span class='varid'>j</span> <span class='layout'>(</span><span class='varid'>v'</span> <span class='varop'>.+.</span> <span class='varid'>sca2</span><span class='layout'>)</span>
                   <span class='varid'>loop2</span> <span class='layout'>(</span><span class='varid'>j</span><span class='varop'>+</span><span class='num'>1</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>v</span> <span class='varop'>.-.</span> <span class='varid'>sca1</span><span class='layout'>)</span>

        <span class='varid'>v'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>loop2</span> <span class='layout'>(</span><span class='varid'>i</span><span class='varop'>+</span><span class='num'>1</span><span class='layout'>)</span> <span class='varid'>v</span>
        <span class='comment'>-- unsafeIOToST (print v')</span>
        <span class='varid'>writeVel</span> <span class='varid'>ps</span> <span class='varid'>i</span> <span class='varid'>v'</span>
        <span class='varid'>writePos</span> <span class='varid'>ps</span> <span class='varid'>i</span> <span class='varop'>$</span> <span class='varid'>move'</span> <span class='varid'>dt</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p</span> <span class='varid'>v'</span> <span class='varid'>m</span><span class='layout'>)</span>
</pre>
]]>
        

    </content>
</entry>

<entry>
    <title>TextMate haskell bundle improvements</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/textmate-haskell-bundle-improvments.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.22</id>

    <published>2009-02-04T05:11:41Z</published>
    <updated>2009-02-04T05:18:37Z</updated>

    <summary>For the last week or so, ozy` has been working on improving the haskell bundle in TextMate. He&apos;s done a lot of work, and it really makes a difference. The changes should be in SVN sometime soon I hope...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="textmate" label="TextMate" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>For the last week or so, ozy` has been working on improving the haskell bundle in TextMate. He's done a lot of work, and it really makes a difference. The changes should be in SVN sometime soon I hope.</p>

<h1>Changelist</h1>

<ul>
<li>Fixed regex for backquote-infix notation</li>
<li>Added highlighting for unit () and empty list []</li>
<li>Fixed up module, class, import, and instance declarations. In particular, some
non-reserved words that are only meaningful in the above contexts are
highlighted appropriately.</li>
<li>Added highlighting for all operators.</li>
<li>Changed scope selectors for some varSyms that were previously highlighted as
"punctuation.separator." This scope is not highlighted by many themes.</li>
<li>Added highlighting for numeric constants. Floats and integrals have separate
scope selectors.</li>
<li>Changed scope selectors for some things like pragma syntax.</li>
<li>Fixed minor errors in regexes that highlight function names.</li>
<li>Modularized a lot of patterns. (There's still a lot to be done here.)</li>
<li>Added highlighting for Prelude type names and constructors. This is scope
aware, in the sense that (eg.) Maybe only gets special treatment in the
context of a type signature. (This is incomplete, though.)</li>
<li>Added highlighting for commas. At the moment this is utterly useless.</li>
<li>Fixed some dumb issues where pragmas would only be scoped as such if they
appeared inside a block comment.</li>
<li>Highlighted a couple of pragma directives. (Incomplete.)</li>
<li>Fixed up the type signature scope a little bit. (Not much.)</li>
</ul>

<p>I've been using the changes while he's been working on them, and they certainly do make the code look quite a bit better. I'll be happy when haskell is a first class language in TextMate, and this is the first big step in getting it there. Hooray!</p>

<p>~ Axman</p>
]]>
        

    </content>
</entry>

<entry>
    <title>N-bodies evolution</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/n-bodies-evolution.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.21</id>

    <published>2009-02-04T02:49:18Z</published>
    <updated>2009-02-04T14:05:23Z</updated>

    <summary>The reason I got interested in this problem was because I decided to take a look at the current haskell submission. I was a little horrified when I say it as all pointer nonsense and back magic. Full of stuff haskell can do fine (And possibly better and more safely that other languages), but should really be avoided where possible. I wanted to see if you could write a fast version, using more accessible techniques.</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Haskell" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Software" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="st" label="ST" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="Software" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>So my last post got submitted to reddit by dons, and someone asked if I translated the code from C, so I thought I'd talk about my evolution of the problem, and how big the difference is runtime from start to finish is so far.</p>

<p>First I should explain the problem. What needs to happen is I take 5 planets and the sun, each with an initial position and velocity, and a mass. Then I set about modifying each body's position and velocity according to the gravitational pull of all the other bodies. For the purposes of this problem, in the end we're only interested in the total energy in the system, which changes as time goes along. For the actual shootout, the bodies must be iterated 50,000,000 times, with a delta time of 0.1 (Not actually sure what that's 0.1 of, possibly days).</p>

<p>The reason I got interested in this problem was because I decided to take a look at the <a href="Http://shootout.alioth.debian.org/u64q/benchmark.php?test=nbody&amp;lang=ghc&amp;id=1">current haskell submission</a>. I was a little horrified when I say it as all pointer nonsense and back magic. Full of stuff haskell can do fine (And possibly better and more safely that other languages), but should really be avoided where possible. I wanted to see if you could write a fast version, using more accessible techniques.</p>

<h2>Lists</h2>

<p>So my initial try used lists. I thought about how I could make is faster, and cool at the same time, and failed by using Control.Parallel, and I think all I have to say about this version that I am not proud of it, and when I just tried to run it with n=50000000, I decided to kill it after it reached 3.3GB of RAM usage in under a minute. Yeah, not great at all.</p>

<h2>Parallel Arrays</h2>

<p>So my next iteration of the problem basically continued on from the list version, but this using parallel arrays. As I'd basically followed in the same steps I'd used for the list version, its performance was on par with that of the list version; it was also killed after using 3GB of RAM in about 30 seconds, and again, I was not proud. It should also be mentioned that neither the list of parallel array versions produced the correct answers with n=1000, so they were never going to be contenders</p>

<h2>STArrays</h2>

<p>It was about this time I discovered the ST monad, and I fell in love (Sort of). The ST monad allows you to write imperative programs, using mutable variables and arrays, in a totally pure way. It's a little like the State monad, but it has a generic state of 'forall s'. I'm not going to go into the details of ST, but if you're interested, check out SPJ's paper on the subject of <a href="Http://research.microsoft.com/en-us/um/people/simonpj/papers/lazy-functional-state-threads.ps.Z">Lazy Functional State Threads</a> (.ps.Z).</p>

<p>This is where I finally started to get some good results. The program runs in about 1.4MB RAM (:O), which means I could actually time its runtime. So I did that, and well, at least it finished. The runtime was <code>14m46.957s</code> according to <code>time</code>, which is still considerably faster than both Pythons, JavaScript under TraceMonkey, ruby, perl, php, and ruby again, but it's slower than Lua, which is 24x slower than the current fastest C++. But I was getting somewhere!</p>

<p>I could see this was the way to go, with memory usage being the most important thing so far, ST made keeping it really low easy as can be.</p>

<p>Now for some speed...</p>

<h2>STUArrays</h2>

<p>I can't remember where I found out about STUArrays, but I could see they were the obvious solution. They're almost as close to C arrays as you're going to get in nice haskell, while still remaining pure, and not so ugly. Basically STUArrays are unboxed arrays (U) in the ST monad (ST). This means that when out put a type into them, instead of putting a pointer to the data in the type inside the array, you put the actual data into the array, so it's all sitting next to each other.</p>

<p>This of course restricts the type you can out into an array somewhat to things like Doubles, Ints, Words, and the few other things with single constructors (This rules out Bools and Integers). There is quite a speed advantage to using STUArrays, but writing your own instance for say <code>MArray (STUArray s) Body (ST s)</code> is a little off putting. Luckily I had talked with Dons about what I was working on, and he'd already started working on something similar. So I nicked his MArray instance, modified it, and... Failed.</p>

<p>For some reason, I kept getting segfaults when trying to get this STUArray stuff to work with my Body type with n > 22:</p>

<pre><span class='hs-keyword'>data</span> <span class='hs-conid'>Vec3</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span>
<span class='hs-keyword'>data</span> <span class='hs-conid'>Body</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>B</span> <span class='hs-layout'>{</span>  
                 <span class='hs-varid'>pos</span> <span class='hs-keyglyph'>::</span>  <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Vec3</span><span class='hs-layout'>,</span>
                 <span class='hs-varid'>vel</span> <span class='hs-keyglyph'>::</span>  <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Vec3</span><span class='hs-layout'>,</span>
                 <span class='hs-varid'>mass</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span>
               <span class='hs-layout'>}</span>
</pre>

<p>I was not happy! And I still have no idea what went wrong.</p>

<p>But I moved on.</p>

<h2>STUArray s Int Double</h2>

<p>I decided I'd avoid the MArray instance completely and use Double STUArrays directly. This turned out to be a good idea indeed, bringing some nice performance benefits.</p>

<p>By doing this, I didn't need to worry about taking out redundant data from the array by fetching a whole Body each time, I could pick out the data I needed, be it the Velocity, Mass or Position, or all three if I needed them all.</p>

<p>With this work, I brought the runtime down to around 2m40 (I think), an  approx. 80% improvement in runtime! This was massive! I was certainly onto something. I was now sitting behind Erlang at 5.9x and below Scheme PLT at 9.1x.</p>

<h2>Performance</h2>

<p>Ok, I'd come this far, but I was now stuck for ways to increase the speed. I'd done some algorithm rejiggering to see if I could gain any speed, and I managed to cut another 10 seconds or so off, but that wasn't going to cut it.</p>

<p>So, I took a look at the performance pages on the wiki. The Arrays page was most useful, suggesting that the use of unsafeRead and unsafeWrite could make huge improvments by removing redundant bounds checking. The floating point page also helped a little, with the suggestion of using the <code>-fexcess-precision</code> flag to speed up the floating point calculations. With these two changes, I managed to cut a whole minute 15 off the time. Yes, I just got a 50% speedup! Now I was getting happy. I was now beating Erlang HiPE, but sadly I was nowhere near C#'s 45 seconds, and definitely nowhere near C++'s 21 seconds. Still, how often do you get to produce a 50% speedup in some already relatively fast code?</p>

<h2>Conclusion and the future</h2>

<p>So what next? Well, I think I can save some more time be using explicit loops with accumulation parameters instead of using <code>STRefs</code> which I have a feeling may carry some overhead. I don't know what kind of gains I can expect, but I doubt they'll be that large. I might also consider making my code even more C like, by directly accessing parts of the arrays directly. I may even get rid of the whole ST thing, and working in IO and with more primitive operations, but by doing that, I'll be moving away from the easier to understand code I have now.</p>

<p>So, what can I conclude from all this? Well, Haskell sure can be fast, while still remaining beautiful. But making it really fast starts to get ugly (Introducing unsafe* does not help :\ ). There are obvious way to do things in haskell, and even some obvious fast ways to do them. But really fast code takes effort (Which is true of  most, if not all languages). I've learnt a lot while writing this program, and I've still got a lot to learn. Wish me luck!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>N-bodies speedup (50%!)</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/02/n-bodies-speedup-50.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.20</id>

    <published>2009-02-03T11:45:33Z</published>
    <updated>2009-02-03T12:21:28Z</updated>

    <summary>So I&apos;ve been playing with this n-bodies thing again, and while I haven&apos;t managed to get all that much closer to the likes of C, C++, or even the current Haskell entry. BUT! I did manage to make my program almost exactly twice as fast as it was. I used a few simple tricks from the performance part of the haskell wiki, mainly the use of unsafeRead and unsafeWrite from the Arrays page, and the use of -fexcess-precision to speed up the Double computation. For those interested in my progress (no one), here&apos;s my current code: {-# OPTIONS -O2 -funbox-strict-fields...</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>So I've been playing with this n-bodies thing again, and while I haven't managed to get all that much closer to the likes of C, C++, or even the current Haskell entry. BUT! I did manage to make my program almost exactly twice as fast as it was.</p>

<p>I used a few simple tricks from the <a href="http://www.haskell.org/haskellwiki/Category:Performance">performance</a> part of the haskell wiki, mainly the use of unsafeRead and unsafeWrite from the Arrays page, and the use of -fexcess-precision to speed up the Double computation.</p>

<p>For those interested in my progress (no one), here's my current code:</p>

<pre><span class='hs-comment'>{-# OPTIONS -O2
-funbox-strict-fields
-fexcess-precision 
-fvia-C
-optc-mfpmath=sse
-optc-msse2#-}</span>

<span class='hs-comment'>{-# LANGUAGE BangPatterns          #-}</span>
<span class='hs-comment'>{-# LANGUAGE UnboxedTuples         #-}</span>
<span class='hs-comment'>{-# LANGUAGE MagicHash             #-}</span>
<span class='hs-comment'>{-# LANGUAGE MultiParamTypeClasses #-}</span>

<span class='hs-keyword'>module</span> <span class='hs-conid'>Main</span> <span class='hs-keyword'>where</span>

<span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Environment</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Array</span><span class='hs-varop'>.</span><span class='hs-conid'>Base</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Exts</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>ST</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Arr</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>ST</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span>
<span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Array</span><span class='hs-varop'>.</span><span class='hs-conid'>Unboxed</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>U</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Array</span><span class='hs-varop'>.</span><span class='hs-conid'>Base</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Storable</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Text</span><span class='hs-varop'>.</span><span class='hs-conid'>Printf</span>
<span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>STRef</span>


<span class='hs-keyword'>data</span> <span class='hs-conid'>Vec3</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span> <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span> <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span>  <span class='hs-comment'>-- deriving (Show)</span>
<span class='hs-keyword'>data</span> <span class='hs-conid'>Body</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>B</span> <span class='hs-layout'>{</span>  
                 <span class='hs-varid'>pos</span> <span class='hs-keyglyph'>::</span>  <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Vec3</span><span class='hs-layout'>,</span>
                 <span class='hs-varid'>vel</span> <span class='hs-keyglyph'>::</span>  <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Vec3</span><span class='hs-layout'>,</span>
                 <span class='hs-varid'>mass</span> <span class='hs-keyglyph'>::</span> <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-conid'>Double</span>
               <span class='hs-layout'>}</span> <span class='hs-comment'>-- deriving (Show)</span>


<span class='hs-definition'>main</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>n</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>getArgs</span> <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>xs</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>null</span> <span class='hs-varid'>xs</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-num'>1000</span> <span class='hs-keyword'>else</span> <span class='hs-layout'>(</span><span class='hs-varid'>readIO</span><span class='hs-varop'>.</span><span class='hs-varid'>head</span><span class='hs-layout'>)</span> <span class='hs-varid'>xs</span>
    <span class='hs-keyword'>let</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span><span class='hs-layout'>,</span><span class='hs-varid'>e'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runST</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
            <span class='hs-varid'>ps</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>planets</span>
            <span class='hs-varid'>offset</span> <span class='hs-varid'>ps</span>
            <span class='hs-varid'>e1</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>energy</span> <span class='hs-varid'>ps</span>
            <span class='hs-varid'>advn</span> <span class='hs-varid'>n</span> <span class='hs-varid'>ps</span>
            <span class='hs-varid'>e2</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>energy</span> <span class='hs-varid'>ps</span>
            <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>e1</span><span class='hs-layout'>,</span><span class='hs-varid'>e2</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>prtnum</span> <span class='hs-varid'>e</span>
    <span class='hs-varid'>prtnum</span> <span class='hs-varid'>e'</span>

<span class='hs-definition'>advn</span> <span class='hs-varid'>n</span> <span class='hs-varid'>ps</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>replicateM_</span> <span class='hs-varid'>n</span> <span class='hs-layout'>(</span><span class='hs-varid'>advance</span> <span class='hs-varid'>deltat</span> <span class='hs-varid'>ps</span><span class='hs-layout'>)</span>



<span class='hs-comment'>------------------</span>

<span class='hs-definition'>offset</span> <span class='hs-varid'>ps</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>v</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newSTRef</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>p</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readPos</span> <span class='hs-varid'>ps</span> <span class='hs-num'>0</span>
    <span class='hs-varid'>ve</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readVel</span> <span class='hs-varid'>ps</span> <span class='hs-num'>0</span>
    <span class='hs-varid'>forM_</span> <span class='hs-varid'>index1</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
        <span class='hs-varid'>vel</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readVel</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span>
        <span class='hs-varid'>m</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readMass</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span>
        <span class='hs-varid'>modifySTRef</span> <span class='hs-varid'>v</span> <span class='hs-layout'>(</span><span class='hs-varop'>.+.</span> <span class='hs-layout'>(</span><span class='hs-varid'>m</span> <span class='hs-varop'>*.</span> <span class='hs-varid'>vel</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>modifySTRef</span> <span class='hs-varid'>v</span> <span class='hs-layout'>(</span><span class='hs-varop'>./</span> <span class='hs-varid'>solar_mass</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>v'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readSTRef</span> <span class='hs-varid'>v</span>
    <span class='hs-varid'>writeVel</span> <span class='hs-varid'>ps</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>ve</span> <span class='hs-varop'>.-.</span> <span class='hs-varid'>v'</span><span class='hs-layout'>)</span>


<span class='hs-definition'>advance</span> <span class='hs-varid'>dt</span> <span class='hs-varid'>ps</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>forM_</span> <span class='hs-varid'>index1</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
        <span class='hs-comment'>-- (B p v m) &lt;- readBody ps i</span>
        <span class='hs-varid'>p</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readPos</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span>
        <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readVel</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span>
        <span class='hs-varid'>m</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readMass</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span>
        <span class='hs-varid'>vvar</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newSTRef</span> <span class='hs-varid'>v</span>

        <span class='hs-varid'>forM_</span> <span class='hs-layout'>(</span><span class='hs-varid'>index2</span> <span class='hs-varid'>i</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>j</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
            <span class='hs-comment'>-- (B p' v' m') &lt;- readBody ps j</span>
            <span class='hs-varid'>p'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readPos</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>j</span>
            <span class='hs-varid'>v'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readVel</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>j</span>
            <span class='hs-varid'>m'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readMass</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>j</span>
            <span class='hs-keyword'>let</span> <span class='hs-varid'>dp</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>p</span> <span class='hs-varop'>.-.</span> <span class='hs-varid'>p'</span>
                <span class='hs-varid'>dst</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mag</span> <span class='hs-varid'>dp</span>
                <span class='hs-varid'>magnit</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>dt</span> <span class='hs-varop'>/</span> <span class='hs-layout'>(</span><span class='hs-varid'>dst</span> <span class='hs-varop'>*</span> <span class='hs-varid'>dst</span> <span class='hs-varop'>*</span> <span class='hs-varid'>dst</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>change</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>magnit</span> <span class='hs-varop'>*.</span> <span class='hs-varid'>dp</span>
                <span class='hs-layout'>(</span><span class='hs-varid'>sca1</span><span class='hs-layout'>,</span><span class='hs-varid'>sca2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>m'</span> <span class='hs-varop'>*.</span> <span class='hs-varid'>change</span><span class='hs-layout'>,</span> <span class='hs-varid'>m</span> <span class='hs-varop'>*.</span> <span class='hs-varid'>change</span><span class='hs-layout'>)</span>
            <span class='hs-varid'>modifySTRef</span> <span class='hs-varid'>vvar</span> <span class='hs-layout'>(</span><span class='hs-varop'>.-.</span> <span class='hs-varid'>sca1</span><span class='hs-layout'>)</span>
            <span class='hs-varid'>writeVel</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>j</span> <span class='hs-layout'>(</span><span class='hs-varid'>v'</span> <span class='hs-varop'>.+.</span> <span class='hs-varid'>sca2</span><span class='hs-layout'>)</span>
        <span class='hs-varid'>vvar'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>nx</span> <span class='hs-varid'>ny</span> <span class='hs-varid'>nz</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readSTRef</span> <span class='hs-varid'>vvar</span>
        <span class='hs-varid'>writeVel'</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span> <span class='hs-varid'>nx</span> <span class='hs-varid'>ny</span> <span class='hs-varid'>nz</span>
        <span class='hs-varid'>writePos</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span> <span class='hs-varop'>$</span> <span class='hs-varid'>move'</span> <span class='hs-varid'>dt</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span> <span class='hs-varid'>p</span> <span class='hs-varid'>vvar'</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span>

<span class='hs-definition'>index1</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-num'>0</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>numPs</span><span class='hs-keyglyph'>]</span>
<span class='hs-comment'>-- index1 = map (*7) [0..numPs]</span>
<span class='hs-definition'>index2</span> <span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-varid'>i</span><span class='hs-varop'>+</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>numPs</span><span class='hs-keyglyph'>]</span>
<span class='hs-comment'>-- index2 = map (\x -&gt; (x*7,x)) [0..numPs]</span>
<span class='hs-comment'>-- index3 = tail . tails $ index1</span>

<span class='hs-definition'>energy</span> <span class='hs-varid'>ps</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>e</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newSTRef</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Double</span><span class='hs-layout'>)</span>

    <span class='hs-varid'>forM_</span> <span class='hs-varid'>index1</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
        <span class='hs-varid'>b1</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readBody</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>i</span>
        <span class='hs-varid'>modifySTRef</span> <span class='hs-varid'>e</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varop'>+</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>kinetic</span> <span class='hs-varid'>b1</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>

        <span class='hs-varid'>forM_</span> <span class='hs-layout'>(</span><span class='hs-varid'>index2</span> <span class='hs-varid'>i</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>j</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
            <span class='hs-varid'>b2</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readBody</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>j</span>
            <span class='hs-keyword'>let</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>potential</span> <span class='hs-varid'>b1</span> <span class='hs-varid'>b2</span>
            <span class='hs-varid'>modifySTRef</span> <span class='hs-varid'>e</span> <span class='hs-layout'>(</span><span class='hs-varid'>subtract</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>readSTRef</span> <span class='hs-varid'>e</span>



<span class='hs-definition'>move</span> <span class='hs-varid'>dt</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span> <span class='hs-varid'>p</span> <span class='hs-varid'>v</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>B</span> <span class='hs-layout'>(</span><span class='hs-varid'>p</span> <span class='hs-varop'>.+.</span> <span class='hs-varid'>dt</span> <span class='hs-varop'>*.</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span> <span class='hs-varid'>v</span> <span class='hs-varid'>m</span>
<span class='hs-definition'>move'</span> <span class='hs-varid'>dt</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span> <span class='hs-varid'>p</span> <span class='hs-varid'>v</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>p</span> <span class='hs-varop'>.+.</span> <span class='hs-varid'>dt</span> <span class='hs-varop'>*.</span> <span class='hs-varid'>v</span>


<span class='hs-comment'>-----------------------</span>

<span class='hs-definition'>writePos</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Vec3</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>()</span>
<span class='hs-definition'>writePos</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-varid'>i'</span>              <span class='hs-varid'>x</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>1</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>y</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>2</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>z</span>


<span class='hs-definition'>writePos'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>()</span>
<span class='hs-definition'>writePos'</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-varop'>!</span><span class='hs-varid'>x</span> <span class='hs-varop'>!</span><span class='hs-varid'>y</span> <span class='hs-varop'>!</span><span class='hs-varid'>z</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-varid'>i'</span>              <span class='hs-varid'>x</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>1</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>y</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>2</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>z</span>


<span class='hs-definition'>writeVel</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Vec3</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>()</span>
<span class='hs-definition'>writeVel</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>vx</span> <span class='hs-varid'>vy</span> <span class='hs-varid'>vz</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>3</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>vx</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>4</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>vy</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>5</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>vz</span>

<span class='hs-definition'>writeVel'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>()</span>
<span class='hs-definition'>writeVel'</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-varop'>!</span><span class='hs-varid'>vx</span> <span class='hs-varop'>!</span><span class='hs-varid'>vy</span> <span class='hs-varop'>!</span><span class='hs-varid'>vz</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>3</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>vx</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>4</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>vy</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>5</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>vz</span>

<span class='hs-comment'>-- writeMass :: STUArray s Int Double -&gt; Int -&gt; Double  -&gt; ST s ()</span>
<span class='hs-comment'>-- writeMass arr i m =</span>
<span class='hs-comment'>--     do</span>
<span class='hs-comment'>--         unsafeWrite arr (i+6) m</span>

<span class='hs-definition'>writeBody</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Body</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>()</span>
<span class='hs-definition'>writeBody</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>B</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span><span class='hs-layout'>)</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>vx</span> <span class='hs-varid'>vy</span> <span class='hs-varid'>vz</span><span class='hs-layout'>)</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-varid'>i'</span><span class='hs-layout'>)</span>            <span class='hs-varid'>x</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>1</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>y</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>2</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>z</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>3</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>vx</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>4</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>vy</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>5</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>vz</span>
                <span class='hs-varid'>unsafeWrite</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>6</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  <span class='hs-varid'>m</span>


<span class='hs-definition'>readPos</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Vec3</span>
<span class='hs-definition'>readPos</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>x</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-varid'>i'</span>
                <span class='hs-varid'>y</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>1</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>z</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>2</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span><span class='hs-layout'>)</span>

<span class='hs-definition'>readVel</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Vec3</span>
<span class='hs-definition'>readVel</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>vx</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>3</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>vy</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>4</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>vz</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>5</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>vx</span> <span class='hs-varid'>vy</span> <span class='hs-varid'>vz</span><span class='hs-layout'>)</span>

<span class='hs-definition'>readMass</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Double</span>
<span class='hs-definition'>readMass</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span> 
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span><span class='hs-varop'>+</span><span class='hs-num'>6</span><span class='hs-layout'>)</span>


<span class='hs-definition'>readBody</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Body</span>
<span class='hs-definition'>readBody</span> <span class='hs-varop'>!</span><span class='hs-varid'>arr</span> <span class='hs-varop'>!</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>case</span> <span class='hs-varid'>i</span><span class='hs-varop'>*</span><span class='hs-num'>7</span> <span class='hs-keyword'>of</span>
        <span class='hs-varid'>i'</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
            <span class='hs-keyword'>do</span>
                <span class='hs-varid'>x</span>   <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-varid'>i'</span>
                <span class='hs-varid'>y</span>   <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>1</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>z</span>   <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>2</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>vx</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>3</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>vy</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>4</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>vz</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>5</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>m</span>   <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>unsafeRead</span> <span class='hs-varid'>arr</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span> <span class='hs-varop'>+#</span> <span class='hs-num'>6</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
                <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>vx</span> <span class='hs-varid'>vy</span> <span class='hs-varid'>vz</span><span class='hs-layout'>)</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span>

<span class='hs-comment'>-----------------------</span>
<span class='hs-definition'>solar_mass</span><span class='hs-layout'>,</span> <span class='hs-varid'>deltat</span><span class='hs-layout'>,</span> <span class='hs-varid'>days_per_year</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Double</span>
<span class='hs-definition'>days_per_year</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>365.24</span>
<span class='hs-definition'>dp</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>days_per_year</span>
<span class='hs-definition'>solar_mass</span>    <span class='hs-keyglyph'>=</span> <span class='hs-num'>4</span> <span class='hs-varop'>*</span> <span class='hs-varid'>pi</span> <span class='hs-varop'>*</span> <span class='hs-varid'>pi</span>
<span class='hs-definition'>deltat</span>       <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.01</span>
<span class='hs-definition'>numPs</span>       <span class='hs-keyglyph'>=</span> <span class='hs-varid'>length</span> <span class='hs-varid'>planetsList</span> <span class='hs-comment'>-</span> <span class='hs-num'>1</span>

<span class='hs-comment'>-- planets'' = newArray (0,(numPs+1)*7) 0 :: ST s (STUArray s Int Double)</span>
    <span class='hs-comment'>-- (B (V 0 0 0) (V 0 0 0) 1)</span>

<span class='hs-comment'>-- ms = U.listArray (0,numPs+1) (map mass planetsList)</span>

<span class='hs-definition'>planets</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>arr</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newArray</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span><span class='hs-layout'>(</span><span class='hs-varid'>numPs</span><span class='hs-varop'>+</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-num'>7</span><span class='hs-layout'>)</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ST</span> <span class='hs-varid'>s</span> <span class='hs-layout'>(</span><span class='hs-conid'>STUArray</span> <span class='hs-varid'>s</span> <span class='hs-conid'>Int</span> <span class='hs-conid'>Double</span><span class='hs-layout'>)</span>
    <span class='hs-comment'>-- unsafeReplaceUArray arr (zip index1 planetsList)</span>
    <span class='hs-varid'>forM_</span> <span class='hs-layout'>(</span><span class='hs-varid'>zip</span> <span class='hs-varid'>index1</span> <span class='hs-varid'>planetsList</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>p</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
            <span class='hs-comment'>-- unsafeIOToST (print (i, pos p))</span>
            <span class='hs-varid'>writeBody</span> <span class='hs-varid'>arr</span> <span class='hs-varid'>i</span> <span class='hs-varid'>p</span>
    <span class='hs-varid'>return</span> <span class='hs-varid'>arr</span>



<span class='hs-definition'>planetsList</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyglyph'>[</span><span class='hs-conid'>B</span>  <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-num'>0.0</span>
            <span class='hs-num'>0.0</span>
            <span class='hs-num'>0.0</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-num'>0.0</span>
            <span class='hs-num'>0.0</span>
            <span class='hs-num'>0.0</span><span class='hs-layout'>)</span> 
        <span class='hs-varid'>solar_mass</span><span class='hs-layout'>,</span>

     <span class='hs-conid'>B</span>  <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-num'>4.84143144246472090e+00</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>1.16032004402742839e+00</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>1.03622044471123109e-01</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-num'>1.66007664274403694e-03</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span> 
            <span class='hs-layout'>(</span><span class='hs-num'>7.69901118419740425e-03</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>6.90460016972063023e-05</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-num'>9.54791938424326609e-04</span> <span class='hs-varop'>*</span> <span class='hs-varid'>solar_mass</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span>

     <span class='hs-conid'>B</span>  <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-num'>8.34336671824457987e+00</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-num'>4.12479856412430479e+00</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>4.03523417114321381e-01</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
        <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>2.76742510726862411e-03</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-num'>4.99852801234917238e-03</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-num'>2.30417297573763929e-05</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-num'>2.85885980666130812e-04</span> <span class='hs-varop'>*</span> <span class='hs-varid'>solar_mass</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span>

     <span class='hs-conid'>B</span>  <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-num'>1.28943695621391310e+01</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>1.51111514016986312e+01</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>2.23307578892655734e-01</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-num'>2.96460137564761618e-03</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-num'>2.37847173959480950e-03</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>2.96589568540237556e-05</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-num'>4.36624404335156298e-05</span> <span class='hs-varop'>*</span> <span class='hs-varid'>solar_mass</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span>

     <span class='hs-conid'>B</span>  <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-num'>1.53796971148509165e+01</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>2.59193146099879641e+01</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-num'>1.79258772950371181e-01</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-conid'>V</span>  <span class='hs-layout'>(</span><span class='hs-num'>2.68067772490389322e-03</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-num'>1.62824170038242295e-03</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span>
            <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>9.51592254519715870e-05</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-varid'>dp</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> 
        <span class='hs-layout'>(</span><span class='hs-num'>5.15138902046611451e-05</span> <span class='hs-varop'>*</span> <span class='hs-varid'>solar_mass</span><span class='hs-layout'>)</span>
    <span class='hs-keyglyph'>]</span>


<span class='hs-comment'>-----------------------</span>

<span class='hs-keyword'>infix</span> <span class='hs-num'>4</span> <span class='hs-varop'>.-.</span>
<span class='hs-keyword'>infix</span> <span class='hs-num'>4</span> <span class='hs-varop'>.+.</span>
<span class='hs-comment'>-- infix 5 .*.</span>
<span class='hs-keyword'>infixr</span> <span class='hs-num'>5</span> <span class='hs-varop'>*.</span>
<span class='hs-keyword'>infixl</span> <span class='hs-num'>5</span> <span class='hs-varop'>./</span>

<span class='hs-comment'>{-# INLINE (.+.) #-}</span>
<span class='hs-comment'>{-# INLINE (.-.) #-}</span>
<span class='hs-comment'>-- {-# INLINE (.*.) #-}</span>
<span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span> <span class='hs-varop'>.+.</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x'</span> <span class='hs-varid'>y'</span> <span class='hs-varid'>z'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>+</span><span class='hs-varid'>x'</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>+</span><span class='hs-varid'>y'</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>z</span><span class='hs-varop'>+</span><span class='hs-varid'>z'</span><span class='hs-layout'>)</span>  
<span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-varid'>z</span><span class='hs-layout'>)</span> <span class='hs-varop'>.-.</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-varid'>x'</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-varid'>y'</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-varid'>z'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> 
    <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span> <span class='hs-varop'>-##</span> <span class='hs-varid'>x'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
      <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span> <span class='hs-varop'>-##</span> <span class='hs-varid'>y'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
      <span class='hs-layout'>(</span><span class='hs-conid'>D</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>z</span> <span class='hs-varop'>-##</span> <span class='hs-varid'>z'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>  
<span class='hs-comment'>-- V x y z .*. V x' y' z' = V (x*x') (y*y') (z*z')</span>

<span class='hs-comment'>{-# INLINE (*.) #-}</span>
<span class='hs-definition'>n</span> <span class='hs-varop'>*.</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span><span class='hs-varop'>*</span><span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span><span class='hs-varop'>*</span><span class='hs-varid'>y</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span><span class='hs-varop'>*</span><span class='hs-varid'>z</span><span class='hs-layout'>)</span>
<span class='hs-comment'>{-# INLINE (./) #-}</span>
<span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span> <span class='hs-varop'>./</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>/</span><span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>/</span><span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>z</span><span class='hs-varop'>/</span><span class='hs-varid'>n</span><span class='hs-layout'>)</span>

<span class='hs-comment'>-- {-# INLINE momentum #-}</span>
<span class='hs-definition'>momentum</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Body</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Vec3</span>
<span class='hs-definition'>momentum</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>v</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>m</span> <span class='hs-varop'>*.</span> <span class='hs-varid'>v</span>

<span class='hs-comment'>{-# INLINE kinetic #-}</span>
<span class='hs-definition'>kinetic</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span>  <span class='hs-num'>0.5</span> <span class='hs-varop'>*</span> <span class='hs-varid'>mass</span> <span class='hs-varid'>x</span> <span class='hs-varop'>*</span> <span class='hs-layout'>(</span><span class='hs-varid'>mag2</span><span class='hs-varop'>.</span><span class='hs-varid'>vel</span><span class='hs-layout'>)</span> <span class='hs-varid'>x</span>

<span class='hs-comment'>-- kinetic'</span>


<span class='hs-definition'>potential</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span>
    <span class='hs-keyword'>let</span> <span class='hs-varid'>dst</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>dist'</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span>
    <span class='hs-keyword'>in</span> <span class='hs-comment'>--if dst &lt;= 0</span>
        <span class='hs-comment'>--then 0</span>
        <span class='hs-comment'>--else </span>
        <span class='hs-layout'>(</span><span class='hs-varid'>mass</span> <span class='hs-varid'>a</span> <span class='hs-varop'>*</span> <span class='hs-varid'>mass</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varop'>/</span> <span class='hs-varid'>dist'</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span>

<span class='hs-comment'>{-# INLINE mag #-}</span>
<span class='hs-definition'>mag</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Vec3</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Double</span>
<span class='hs-definition'>mag</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sqrt</span> <span class='hs-varop'>.</span> <span class='hs-varid'>mag2</span>

<span class='hs-comment'>{-# INLINE mag2 #-}</span>
<span class='hs-definition'>mag2</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>z</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span><span class='hs-varop'>*</span><span class='hs-varid'>x</span> <span class='hs-varop'>+</span> <span class='hs-varid'>y</span><span class='hs-varop'>*</span><span class='hs-varid'>y</span> <span class='hs-varop'>+</span> <span class='hs-varid'>z</span><span class='hs-varop'>*</span><span class='hs-varid'>z</span>

<span class='hs-comment'>{-# INLINE dist #-}</span>
<span class='hs-definition'>dist</span> <span class='hs-varid'>v1</span> <span class='hs-varid'>v2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sqrt</span> <span class='hs-varop'>$</span> <span class='hs-varid'>dist2</span> <span class='hs-varid'>v1</span> <span class='hs-varid'>v2</span>

<span class='hs-comment'>{-# INLINE dist2 #-}</span>
<span class='hs-definition'>dist2</span> <span class='hs-varid'>v1</span> <span class='hs-varid'>v2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mag2</span> <span class='hs-varop'>$</span> <span class='hs-varid'>v1</span> <span class='hs-varop'>.-.</span> <span class='hs-varid'>v2</span>

<span class='hs-comment'>{-# INLINE dist' #-}</span>
<span class='hs-definition'>dist'</span> <span class='hs-varid'>b1</span> <span class='hs-varid'>b2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>dist</span> <span class='hs-layout'>(</span><span class='hs-varid'>pos</span> <span class='hs-varid'>b1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>pos</span> <span class='hs-varid'>b2</span><span class='hs-layout'>)</span>

<span class='hs-definition'>prtnum</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Double</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<span class='hs-definition'>prtnum</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>putStrLn</span> <span class='hs-varop'>$</span> <span class='hs-varid'>printf</span> <span class='hs-str'>"%.9f"</span> <span class='hs-varid'>x</span>

<span class='hs-comment'>-------------------- tests</span>

<span class='hs-definition'>thing2</span> <span class='hs-varid'>pla</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>arr</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>pla</span>
    <span class='hs-varid'>unsafeIOToST</span> <span class='hs-layout'>(</span><span class='hs-varid'>putStrLn</span> <span class='hs-str'>"thing2"</span><span class='hs-layout'>)</span>
    <span class='hs-varid'>forM_</span> <span class='hs-keyglyph'>[</span><span class='hs-num'>0</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>numPs</span><span class='hs-varop'>*</span><span class='hs-num'>7</span><span class='hs-keyglyph'>]</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
        <span class='hs-varid'>p</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readArray</span> <span class='hs-varid'>arr</span> <span class='hs-varid'>i</span>
        <span class='hs-varid'>unsafeIOToST</span> <span class='hs-layout'>(</span><span class='hs-varid'>print</span> <span class='hs-layout'>(</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>p</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>

<span class='hs-definition'>thing3</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>arr</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>planets</span>
    <span class='hs-varid'>offset</span> <span class='hs-varid'>arr</span>
    <span class='hs-varid'>thing2</span> <span class='hs-varid'>planets</span>
    <span class='hs-varid'>unsafeIOToST</span> <span class='hs-layout'>(</span><span class='hs-varid'>putStrLn</span> <span class='hs-str'>"\n"</span><span class='hs-layout'>)</span>
    <span class='hs-comment'>-- thing2 arr</span>
    <span class='hs-varid'>e</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>energy</span> <span class='hs-varid'>arr</span>
    <span class='hs-varid'>return</span> <span class='hs-varid'>e</span></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>STUArray woes</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/01/stuarray-woes.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.19</id>

    <published>2009-01-30T09:41:33Z</published>
    <updated>2009-01-30T09:50:27Z</updated>

    <summary><![CDATA[little while ago, I was trying to write a nice, clear version of the [language shootout n-body problem](http://shootout.alioth.debian.org/u64q/benchmark.php?test=nbody&lang=all), using the ST monad, and STUArrays. Though I ran into a snag;]]></summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
    <category term="array" label="Array" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="haskell" label="Haskell" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="st" label="ST" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>So a little while ago, I was trying to write a nice, clear version of the <a href="http://shootout.alioth.debian.org/u64q/benchmark.php?test=nbody&amp;lang=all">language shootout n-body problem</a>, using the ST monad, and STUArrays. Though I ran into a snag; I was getting segmentation faults, for very small values of n (&lt; 23), and not knowing enough about such things, I have no idea where to begin in diagnosing the problem. So, I shall post my code here, and hope that someone might have some ideas. I've talked to Don Stewart about it, but he hasn't got back to me yet.</p>

<p>(All the MUArray instance stuff is from Don's work, which I nicked)</p>

<p>So, here we have it:</p>

<pre><span class='varop'>&gt;</span> <span class='comment'>{-# OPTIONS -O2 -funbox-strict-fields #-}</span>
<span class='varop'>&gt;</span> <span class='comment'>{-# LANGUAGE BangPatterns          #-}</span>
<span class='varop'>&gt;</span> <span class='comment'>{-# LANGUAGE UnboxedTuples         #-}</span>
<span class='varop'>&gt;</span> <span class='comment'>{-# LANGUAGE MagicHash             #-}</span>
<span class='varop'>&gt;</span> <span class='comment'>{-# LANGUAGE MultiParamTypeClasses #-}</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='keyword'>module</span> <span class='conid'>Main</span> <span class='keyword'>where</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>System</span><span class='varop'>.</span><span class='conid'>Environment</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>Data</span><span class='varop'>.</span><span class='conid'>Array</span><span class='varop'>.</span><span class='conid'>Base</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>GHC</span><span class='varop'>.</span><span class='conid'>Exts</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>GHC</span><span class='varop'>.</span><span class='conid'>ST</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>GHC</span><span class='varop'>.</span><span class='conid'>Arr</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>Control</span><span class='varop'>.</span><span class='conid'>Monad</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>Control</span><span class='varop'>.</span><span class='conid'>Monad</span><span class='varop'>.</span><span class='conid'>ST</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>Data</span><span class='varop'>.</span><span class='conid'>List</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>Foreign</span><span class='varop'>.</span><span class='conid'>Storable</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>Text</span><span class='varop'>.</span><span class='conid'>Printf</span>
<span class='varop'>&gt;</span> <span class='keyword'>import</span> <span class='conid'>Data</span><span class='varop'>.</span><span class='conid'>STRef</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='keyword'>data</span> <span class='conid'>Vec3</span> <span class='keyglyph'>=</span> <span class='conid'>V</span> <span class='varop'>!</span><span class='conid'>Double</span> <span class='varop'>!</span><span class='conid'>Double</span> <span class='varop'>!</span><span class='conid'>Double</span> <span class='keyword'>deriving</span> <span class='layout'>(</span><span class='conid'>Show</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> <span class='keyword'>data</span> <span class='conid'>Body</span> <span class='keyglyph'>=</span> <span class='conid'>B</span> <span class='layout'>{</span>  
<span class='varop'>&gt;</span>                  <span class='varid'>pos</span> <span class='keyglyph'>::</span>  <span class='comment'>{-# UNPACK #-}</span> <span class='varop'>!</span><span class='conid'>Vec3</span><span class='layout'>,</span>
<span class='varop'>&gt;</span>                  <span class='varid'>vel</span> <span class='keyglyph'>::</span>  <span class='comment'>{-# UNPACK #-}</span> <span class='varop'>!</span><span class='conid'>Vec3</span><span class='layout'>,</span>
<span class='varop'>&gt;</span>                  <span class='varid'>mass</span> <span class='keyglyph'>::</span> <span class='varop'>!</span><span class='conid'>Double</span>
<span class='varop'>&gt;</span>                <span class='layout'>}</span> <span class='keyword'>deriving</span> <span class='layout'>(</span><span class='conid'>Show</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>main</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>     <span class='varid'>n</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>getArgs</span> <span class='varop'>&gt;&gt;=</span> <span class='keyglyph'>\</span><span class='varid'>xs</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>if</span> <span class='varid'>null</span> <span class='varid'>xs</span> <span class='keyword'>then</span> <span class='varid'>return</span> <span class='num'>1000</span> <span class='keyword'>else</span> <span class='layout'>(</span><span class='varid'>readIO</span><span class='varop'>.</span><span class='varid'>head</span><span class='layout'>)</span> <span class='varid'>xs</span>
<span class='varop'>&gt;</span>     <span class='keyword'>let</span> <span class='layout'>(</span><span class='varid'>e</span><span class='layout'>,</span><span class='varid'>e'</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='varid'>runST</span> <span class='varop'>$</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>             <span class='varid'>ps</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>planets</span>
<span class='varop'>&gt;</span>             <span class='varid'>offset</span> <span class='varid'>ps</span>
<span class='varop'>&gt;</span>             <span class='varid'>e1</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>energy</span> <span class='varid'>ps</span>
<span class='varop'>&gt;</span>             <span class='varid'>advn</span> <span class='varid'>n</span> <span class='varid'>ps</span>
<span class='varop'>&gt;</span>             <span class='varid'>e2</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>energy</span> <span class='varid'>ps</span>
<span class='varop'>&gt;</span>             <span class='varid'>return</span> <span class='layout'>(</span><span class='varid'>e1</span><span class='layout'>,</span><span class='varid'>e2</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     <span class='varid'>prtnum</span> <span class='varid'>e</span>
<span class='varop'>&gt;</span>     <span class='varid'>prtnum</span> <span class='varid'>e'</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>offset</span> <span class='varid'>ps</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>     <span class='varid'>v</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>newSTRef</span> <span class='layout'>(</span><span class='conid'>V</span> <span class='num'>0</span> <span class='num'>0</span> <span class='num'>0</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p</span> <span class='varid'>ve</span> <span class='varid'>m</span><span class='layout'>)</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readArray</span> <span class='varid'>ps</span> <span class='num'>0</span>
<span class='varop'>&gt;</span>     <span class='varid'>forM_</span> <span class='keyglyph'>[</span><span class='num'>0</span><span class='keyglyph'>..</span><span class='varid'>numPs</span><span class='keyglyph'>]</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>i</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>         <span class='varid'>p</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readArray</span> <span class='varid'>ps</span> <span class='varid'>i</span>
<span class='varop'>&gt;</span>         <span class='varid'>modifySTRef</span> <span class='varid'>v</span> <span class='layout'>(</span><span class='varop'>.+.</span> <span class='varid'>momentum</span> <span class='varid'>p</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     <span class='varid'>modifySTRef</span> <span class='varid'>v</span> <span class='layout'>(</span><span class='varop'>./</span> <span class='varid'>solar_mass</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     <span class='varid'>v'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readSTRef</span> <span class='varid'>v</span>
<span class='varop'>&gt;</span>     <span class='varid'>writeArray</span> <span class='varid'>ps</span> <span class='num'>0</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p</span> <span class='layout'>(</span><span class='varid'>ve</span><span class='varop'>.-.</span> <span class='varid'>v'</span><span class='layout'>)</span> <span class='varid'>m</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span>     
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>advn</span> <span class='num'>0</span> <span class='varid'>ps</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>     <span class='varid'>return</span> <span class='varid'>ps</span>
<span class='varop'>&gt;</span> <span class='varid'>advn</span> <span class='varid'>n</span> <span class='varid'>ps</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>     <span class='varid'>advance</span> <span class='varid'>deltat</span> <span class='varid'>ps</span>
<span class='varop'>&gt;</span>     <span class='comment'>-- e &lt;- energy ps</span>
<span class='varop'>&gt;</span>     <span class='comment'>-- unsafeIOToST (prtnum e)</span>
<span class='varop'>&gt;</span>     <span class='varid'>advn</span> <span class='layout'>(</span><span class='varid'>n</span><span class='comment'>-</span><span class='num'>1</span><span class='layout'>)</span> <span class='varid'>ps</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>advance</span> <span class='varid'>dt</span> <span class='varid'>ps</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>     <span class='varid'>forM_</span> <span class='keyglyph'>[</span><span class='num'>0</span><span class='keyglyph'>..</span><span class='varid'>numPs</span><span class='keyglyph'>]</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>i</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p</span> <span class='varid'>v</span> <span class='varid'>m</span><span class='layout'>)</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readArray</span> <span class='varid'>ps</span> <span class='varid'>i</span>
<span class='varop'>&gt;</span>         <span class='varid'>vvar</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>newSTRef</span> <span class='varid'>v</span>
<span class='varop'>&gt;</span>         <span class='varid'>forM_</span> <span class='keyglyph'>[</span><span class='varid'>i</span><span class='varop'>+</span><span class='num'>1</span><span class='keyglyph'>..</span><span class='varid'>numPs</span><span class='keyglyph'>]</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>j</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p'</span> <span class='varid'>v'</span> <span class='varid'>m'</span><span class='layout'>)</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readArray</span> <span class='varid'>ps</span> <span class='varid'>j</span>
<span class='varop'>&gt;</span>             <span class='keyword'>let</span> <span class='varid'>dp</span> <span class='keyglyph'>=</span> <span class='varid'>p</span> <span class='varop'>.-.</span> <span class='varid'>p'</span>
<span class='varop'>&gt;</span>                 <span class='varid'>dst</span> <span class='keyglyph'>=</span> <span class='varid'>mag</span> <span class='varid'>dp</span>
<span class='varop'>&gt;</span>                 <span class='varid'>magnit</span> <span class='keyglyph'>=</span> <span class='varid'>dt</span> <span class='varop'>/</span> <span class='layout'>(</span><span class='varid'>dst</span> <span class='varop'>*</span> <span class='varid'>dst</span> <span class='varop'>*</span> <span class='varid'>dst</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>                 <span class='varid'>change</span> <span class='keyglyph'>=</span> <span class='varid'>magnit</span> <span class='varop'>*.</span> <span class='varid'>dp</span>
<span class='varop'>&gt;</span>                 <span class='varid'>sca1</span> <span class='keyglyph'>=</span> <span class='varid'>m'</span> <span class='varop'>*.</span> <span class='varid'>change</span>
<span class='varop'>&gt;</span>                 <span class='varid'>sca2</span> <span class='keyglyph'>=</span> <span class='varid'>m</span> <span class='varop'>*.</span> <span class='varid'>change</span>
<span class='varop'>&gt;</span>             <span class='comment'>-- writeArray ps I (B p (v .-. sca1) m)</span>
<span class='varop'>&gt;</span>             <span class='varid'>modifySTRef</span> <span class='varid'>vvar</span> <span class='layout'>(</span><span class='varop'>.-.</span> <span class='varid'>sca1</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='varid'>writeArray</span> <span class='varid'>ps</span> <span class='varid'>j</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p'</span> <span class='layout'>(</span><span class='varid'>v'</span> <span class='varop'>.+.</span> <span class='varid'>sca2</span><span class='layout'>)</span> <span class='varid'>m'</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>         <span class='varid'>vvar'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readSTRef</span> <span class='varid'>vvar</span>
<span class='varop'>&gt;</span>         <span class='varid'>writeArray</span> <span class='varid'>ps</span> <span class='conid'>I</span> <span class='layout'>(</span><span class='varid'>move</span> <span class='varid'>dt</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p</span> <span class='varid'>vvar'</span> <span class='varid'>m</span><span class='layout'>)</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>energy</span> <span class='varid'>ps</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>     <span class='varid'>e</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>newSTRef</span> <span class='layout'>(</span><span class='num'>0</span> <span class='keyglyph'>::</span> <span class='conid'>Double</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     
<span class='varop'>&gt;</span>     <span class='varid'>forM_</span> <span class='keyglyph'>[</span><span class='num'>0</span><span class='keyglyph'>..</span><span class='varid'>numPs</span><span class='keyglyph'>]</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>i</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>         <span class='varid'>b1</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readArray</span> <span class='varid'>ps</span> <span class='varid'>i</span>
<span class='varop'>&gt;</span>         <span class='varid'>modifySTRef</span> <span class='varid'>e</span> <span class='layout'>(</span><span class='layout'>(</span><span class='varop'>+</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>kinetic</span> <span class='varid'>b</span><span class='layout'>)</span><span class='num'>1</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>         
<span class='varop'>&gt;</span>         <span class='varid'>forM_</span> <span class='keyglyph'>[</span><span class='varid'>i</span><span class='varop'>+</span><span class='num'>1</span><span class='keyglyph'>..</span><span class='varid'>numPs</span><span class='keyglyph'>]</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>j</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>             <span class='varid'>b2</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readArray</span> <span class='varid'>ps</span> <span class='varid'>j</span>
<span class='varop'>&gt;</span>             <span class='keyword'>let</span> <span class='varid'>x</span> <span class='keyglyph'>=</span> <span class='varid'>potential</span> <span class='varid'>b1</span> <span class='varid'>b2</span>
<span class='varop'>&gt;</span>             <span class='varid'>modifySTRef</span> <span class='varid'>e</span> <span class='layout'>(</span><span class='varid'>subtract</span> <span class='varid'>x</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     <span class='varid'>e'</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>readSTRef</span> <span class='varid'>e</span>
<span class='varop'>&gt;</span>     <span class='varid'>return</span> <span class='varid'>e'</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>move</span> <span class='varid'>dt</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='varid'>p</span> <span class='varid'>v</span> <span class='varid'>m</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='conid'>B</span> <span class='layout'>(</span><span class='varid'>p</span> <span class='varop'>.+.</span> <span class='varid'>dt</span> <span class='varop'>*.</span> <span class='varid'>v</span><span class='layout'>)</span> <span class='varid'>v</span> <span class='varid'>m</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>-----------------------</span>
<span class='varop'>&gt;</span> <span class='varid'>solar_mass</span><span class='layout'>,</span> <span class='varid'>deltat</span><span class='layout'>,</span> <span class='varid'>days_per_year</span> <span class='keyglyph'>::</span> <span class='conid'>Double</span>
<span class='varop'>&gt;</span> <span class='varid'>days_per_year</span> <span class='keyglyph'>=</span> <span class='num'>365.24</span>
<span class='varop'>&gt;</span> <span class='varid'>dp</span> <span class='keyglyph'>=</span> <span class='varid'>days_per_year</span>
<span class='varop'>&gt;</span> <span class='varid'>solar_mass</span>    <span class='keyglyph'>=</span> <span class='num'>4</span> <span class='varop'>*</span> <span class='varid'>pi</span> <span class='varop'>*</span> <span class='varid'>pi</span>
<span class='varop'>&gt;</span> <span class='varid'>deltat</span>       <span class='keyglyph'>=</span> <span class='num'>0.01</span>
<span class='varop'>&gt;</span> <span class='varid'>numPs</span>       <span class='keyglyph'>=</span> <span class='varid'>length</span> <span class='varid'>planets'</span> <span class='comment'>-</span> <span class='num'>1</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>planets''</span> <span class='keyglyph'>=</span> <span class='varid'>newArray_</span> <span class='layout'>(</span><span class='num'>0</span><span class='layout'>,</span><span class='varid'>numPs</span><span class='layout'>)</span> <span class='keyglyph'>::</span> <span class='conid'>ST</span> <span class='varid'>s</span> <span class='layout'>(</span><span class='conid'>STUArray</span> <span class='varid'>s</span> <span class='conid'>Int</span> <span class='conid'>Body</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     <span class='comment'>-- (B (V 0 0 0) (V 0 0 0) 1)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>planets</span> <span class='keyglyph'>=</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>     <span class='varid'>arr</span> <span class='keyglyph'>&lt;-</span> <span class='varid'>planets''</span>
<span class='varop'>&gt;</span>     <span class='varid'>forM_</span> <span class='layout'>(</span><span class='varid'>zip</span> <span class='keyglyph'>[</span><span class='num'>0</span><span class='keyglyph'>..</span><span class='keyglyph'>]</span> <span class='varid'>planets'</span><span class='layout'>)</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='layout'>(</span><span class='varid'>i</span><span class='layout'>,</span><span class='varid'>p</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span> <span class='keyword'>do</span>
<span class='varop'>&gt;</span>         <span class='varid'>writeArray</span> <span class='varid'>arr</span> <span class='conid'>I</span> <span class='varid'>p</span>
<span class='varop'>&gt;</span>     <span class='varid'>return</span> <span class='varid'>arr</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>planets'</span> <span class='keyglyph'>=</span>
<span class='varop'>&gt;</span>     <span class='keyglyph'>[</span><span class='conid'>B</span>  <span class='layout'>(</span><span class='conid'>V</span>  <span class='num'>0.0</span>
<span class='varop'>&gt;</span>             <span class='num'>0.0</span>
<span class='varop'>&gt;</span>             <span class='num'>0.0</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='conid'>V</span>  <span class='num'>0.0</span>
<span class='varop'>&gt;</span>             <span class='num'>0.0</span>
<span class='varop'>&gt;</span>             <span class='num'>0.0</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='varid'>solar_mass</span><span class='layout'>,</span>
<span class='varop'>&gt;</span>         
<span class='varop'>&gt;</span>      <span class='conid'>B</span>  <span class='layout'>(</span><span class='conid'>V</span>  <span class='num'>4.84143144246472090e+00</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='comment'>-</span><span class='num'>1.16032004402742839e+00</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='comment'>-</span><span class='num'>1.03622044471123109e-01</span><span class='layout'>)</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='conid'>V</span>  <span class='layout'>(</span><span class='num'>1.66007664274403694e-03</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='num'>7.69901118419740425e-03</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='layout'>(</span><span class='comment'>-</span><span class='num'>6.90460016972063023e-05</span><span class='layout'>)</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='num'>9.54791938424326609e-04</span> <span class='varop'>*</span> <span class='varid'>solar_mass</span><span class='layout'>)</span><span class='layout'>,</span>
<span class='varop'>&gt;</span>         
<span class='varop'>&gt;</span>      <span class='conid'>B</span>  <span class='layout'>(</span><span class='conid'>V</span>  <span class='num'>8.34336671824457987e+00</span>
<span class='varop'>&gt;</span>             <span class='num'>4.12479856412430479e+00</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='comment'>-</span><span class='num'>4.03523417114321381e-01</span><span class='layout'>)</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='conid'>V</span>  <span class='layout'>(</span><span class='layout'>(</span><span class='comment'>-</span><span class='num'>2.76742510726862411e-03</span><span class='layout'>)</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='num'>4.99852801234917238e-03</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='num'>2.30417297573763929e-05</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='num'>2.85885980666130812e-04</span> <span class='varop'>*</span> <span class='varid'>solar_mass</span><span class='layout'>)</span><span class='layout'>,</span>
<span class='varop'>&gt;</span>         
<span class='varop'>&gt;</span>      <span class='conid'>B</span>  <span class='layout'>(</span><span class='conid'>V</span>  <span class='num'>1.28943695621391310e+01</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='comment'>-</span><span class='num'>1.51111514016986312e+01</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='comment'>-</span><span class='num'>2.23307578892655734e-01</span><span class='layout'>)</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='conid'>V</span>  <span class='layout'>(</span><span class='num'>2.96460137564761618e-03</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='num'>2.37847173959480950e-03</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='layout'>(</span><span class='comment'>-</span><span class='num'>2.96589568540237556e-05</span><span class='layout'>)</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='num'>4.36624404335156298e-05</span> <span class='varop'>*</span> <span class='varid'>solar_mass</span><span class='layout'>)</span><span class='layout'>,</span>
<span class='varop'>&gt;</span>         
<span class='varop'>&gt;</span>      <span class='conid'>B</span>  <span class='layout'>(</span><span class='conid'>V</span>  <span class='num'>1.53796971148509165e+01</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='comment'>-</span><span class='num'>2.59193146099879641e+01</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='num'>1.79258772950371181e-01</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='conid'>V</span>  <span class='layout'>(</span><span class='num'>2.68067772490389322e-03</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='num'>1.62824170038242295e-03</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>             <span class='layout'>(</span><span class='layout'>(</span><span class='comment'>-</span><span class='num'>9.51592254519715870e-05</span><span class='layout'>)</span><span class='varop'>*</span><span class='varid'>dp</span><span class='layout'>)</span><span class='layout'>)</span> 
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='num'>5.15138902046611451e-05</span> <span class='varop'>*</span> <span class='varid'>solar_mass</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     <span class='keyglyph'>]</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>-----------------------</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='keyword'>infix</span> <span class='num'>4</span> <span class='varop'>.-.</span>
<span class='varop'>&gt;</span> <span class='keyword'>infix</span> <span class='num'>4</span> <span class='varop'>.+.</span>
<span class='varop'>&gt;</span> <span class='comment'>-- infix 5 .*.</span>
<span class='varop'>&gt;</span> <span class='keyword'>infixr</span> <span class='num'>5</span> <span class='varop'>*.</span>
<span class='varop'>&gt;</span> <span class='keyword'>infixl</span> <span class='num'>5</span> <span class='varop'>./</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE (.+.) #-}</span>
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE (.-.) #-}</span>
<span class='varop'>&gt;</span> <span class='comment'>-- {-# INLINE (.*.) #-}</span>
<span class='varop'>&gt;</span> <span class='conid'>V</span> <span class='varid'>x</span> <span class='varid'>y</span> <span class='varid'>z</span> <span class='varop'>.+.</span> <span class='conid'>V</span> <span class='varid'>x'</span> <span class='varid'>y'</span> <span class='varid'>z'</span> <span class='keyglyph'>=</span> <span class='conid'>V</span> <span class='layout'>(</span><span class='varid'>x</span><span class='varop'>+</span><span class='varid'>x'</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>y</span><span class='varop'>+</span><span class='varid'>y'</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>z</span><span class='varop'>+</span><span class='varid'>z'</span><span class='layout'>)</span>  
<span class='varop'>&gt;</span> <span class='conid'>V</span> <span class='varid'>x</span> <span class='varid'>y</span> <span class='varid'>z</span> <span class='varop'>.-.</span> <span class='conid'>V</span> <span class='varid'>x'</span> <span class='varid'>y'</span> <span class='varid'>z'</span> <span class='keyglyph'>=</span> <span class='conid'>V</span> <span class='layout'>(</span><span class='varid'>x</span><span class='comment'>-</span><span class='varid'>x'</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>y</span><span class='comment'>-</span><span class='varid'>y'</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>z</span><span class='comment'>-</span><span class='varid'>z'</span><span class='layout'>)</span>  
<span class='varop'>&gt;</span> <span class='comment'>-- V x y z .*. V x' y' z' = V (x*x') (y*y') (z*z')</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE (*.) #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>n</span> <span class='varop'>*.</span> <span class='layout'>(</span><span class='conid'>V</span> <span class='varid'>x</span> <span class='varid'>y</span> <span class='varid'>z</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='conid'>V</span> <span class='layout'>(</span><span class='varid'>n</span><span class='varop'>*</span><span class='varid'>x</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>n</span><span class='varop'>*</span><span class='varid'>y</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>n</span><span class='varop'>*</span><span class='varid'>z</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE (./) #-}</span>
<span class='varop'>&gt;</span> <span class='conid'>V</span> <span class='varid'>x</span> <span class='varid'>y</span> <span class='varid'>z</span> <span class='varop'>./</span> <span class='varid'>n</span> <span class='keyglyph'>=</span> <span class='conid'>V</span> <span class='layout'>(</span><span class='varid'>x</span><span class='varop'>/</span><span class='varid'>n</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>y</span><span class='varop'>/</span><span class='varid'>n</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>z</span><span class='varop'>/</span><span class='varid'>n</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE momentum #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>momentum</span> <span class='keyglyph'>::</span> <span class='conid'>Body</span> <span class='keyglyph'>-&gt;</span> <span class='conid'>Vec3</span>
<span class='varop'>&gt;</span> <span class='varid'>momentum</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='keyword'>_</span> <span class='varid'>v</span> <span class='varid'>m</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='varid'>m</span> <span class='varop'>*.</span> <span class='varid'>v</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE kinetic #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>kinetic</span> <span class='varid'>x</span> <span class='keyglyph'>=</span>  <span class='num'>0.5</span> <span class='varop'>*</span> <span class='varid'>mass</span> <span class='varid'>x</span> <span class='varop'>*</span> <span class='layout'>(</span><span class='varid'>mag2</span><span class='varop'>.</span><span class='varid'>vel</span><span class='layout'>)</span> <span class='varid'>x</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>potential</span> <span class='varid'>a</span> <span class='varid'>b</span> <span class='keyglyph'>=</span>
<span class='varop'>&gt;</span>     <span class='keyword'>let</span> <span class='varid'>dst</span> <span class='keyglyph'>=</span> <span class='varid'>dist'</span> <span class='varid'>a</span> <span class='varid'>b</span>
<span class='varop'>&gt;</span>     <span class='keyword'>in</span> <span class='keyword'>if</span> <span class='varid'>dst</span> <span class='varop'>&lt;=</span> <span class='num'>0</span>
<span class='varop'>&gt;</span>         <span class='keyword'>then</span> <span class='num'>0</span>
<span class='varop'>&gt;</span>         <span class='keyword'>else</span> <span class='layout'>(</span><span class='varid'>mass</span> <span class='varid'>a</span> <span class='varop'>*</span> <span class='varid'>mass</span> <span class='varid'>b</span><span class='layout'>)</span> <span class='varop'>/</span> <span class='varid'>dist'</span> <span class='varid'>a</span> <span class='varid'>b</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE mag #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>mag</span> <span class='keyglyph'>::</span> <span class='conid'>Vec3</span> <span class='keyglyph'>-&gt;</span> <span class='conid'>Double</span>
<span class='varop'>&gt;</span> <span class='varid'>mag</span> <span class='keyglyph'>=</span> <span class='varid'>sqrt</span> <span class='varop'>.</span> <span class='varid'>mag2</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE mag2 #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>mag2</span> <span class='layout'>(</span><span class='conid'>V</span> <span class='varid'>x</span> <span class='varid'>y</span> <span class='varid'>z</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='varid'>x</span><span class='varop'>*</span><span class='varid'>x</span> <span class='varop'>+</span> <span class='varid'>y</span><span class='varop'>*</span><span class='varid'>y</span> <span class='varop'>+</span> <span class='varid'>z</span><span class='varop'>*</span><span class='varid'>z</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE dist #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>dist</span> <span class='varid'>v1</span> <span class='varid'>v2</span> <span class='keyglyph'>=</span> <span class='varid'>sqrt</span> <span class='varop'>$</span> <span class='varid'>dist2</span> <span class='varid'>v1</span> <span class='varid'>v2</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE dist2 #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>dist2</span> <span class='varid'>v1</span> <span class='varid'>v2</span> <span class='keyglyph'>=</span> <span class='varid'>mag2</span> <span class='varop'>$</span> <span class='varid'>v1</span> <span class='varop'>.-.</span> <span class='varid'>v2</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>{-# INLINE dist' #-}</span>
<span class='varop'>&gt;</span> <span class='varid'>dist'</span> <span class='varid'>b1</span> <span class='varid'>b2</span> <span class='keyglyph'>=</span> <span class='varid'>dist</span> <span class='layout'>(</span><span class='varid'>pos</span> <span class='varid'>b1</span><span class='layout'>)</span> <span class='layout'>(</span><span class='varid'>pos</span> <span class='varid'>b2</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='varid'>prtnum</span> <span class='varid'>x</span> <span class='keyglyph'>=</span> <span class='varid'>putStrLn</span> <span class='varop'>$</span> <span class='varid'>printf</span> <span class='str'>"%.9f"</span> <span class='varid'>x</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='comment'>--------------------</span>
<span class='varop'>&gt;</span> <span class='varid'>bodyScale</span> <span class='keyglyph'>::</span> <span class='conid'>Int</span><span class='cpp'>#</span> <span class='keyglyph'>-&gt;</span> <span class='conid'>Int</span><span class='cpp'>#</span>
<span class='varop'>&gt;</span> <span class='varid'>bodyScale</span> <span class='varid'>n</span> <span class='keyglyph'>=</span> <span class='layout'>(</span><span class='varid'>scale</span> <span class='varop'>*#</span> <span class='num'>7</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varop'>*#</span> <span class='varid'>n</span>
<span class='varop'>&gt;</span>      <span class='keyword'>where</span> <span class='conid'>I</span><span class='cpp'>#</span> <span class='varid'>scale</span> <span class='keyglyph'>=</span> <span class='varid'>sizeOf</span> <span class='layout'>(</span><span class='varid'>undefined</span> <span class='keyglyph'>::</span> <span class='conid'>Double</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span> <span class='keyword'>instance</span> <span class='conid'>MArray</span> <span class='layout'>(</span><span class='conid'>STUArray</span> <span class='varid'>s</span><span class='layout'>)</span> <span class='conid'>Body</span> <span class='layout'>(</span><span class='conid'>ST</span> <span class='varid'>s</span><span class='layout'>)</span> <span class='keyword'>where</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span>     <span class='comment'>{-# INLINE getBounds #-}</span>
<span class='varop'>&gt;</span>     <span class='varid'>getBounds</span> <span class='layout'>(</span><span class='conid'>STUArray</span> <span class='varid'>l</span> <span class='varid'>h</span> <span class='keyword'>_</span> <span class='keyword'>_</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='varid'>return</span> <span class='layout'>(</span><span class='varid'>l</span><span class='layout'>,</span><span class='varid'>h</span><span class='layout'>)</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span>     <span class='comment'>{-# INLINE getNumElements #-}</span>
<span class='varop'>&gt;</span>     <span class='varid'>getNumElements</span> <span class='layout'>(</span><span class='conid'>STUArray</span> <span class='keyword'>_</span> <span class='keyword'>_</span> <span class='varid'>n</span> <span class='keyword'>_</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='varid'>return</span> <span class='varid'>n</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span>     <span class='comment'>{-# INLINE unsafeNewArray_ #-}</span>
<span class='varop'>&gt;</span>     <span class='varid'>unsafeNewArray_</span> <span class='layout'>(</span><span class='varid'>l</span><span class='layout'>,</span><span class='varid'>u</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='varid'>unsafeNewArraySTUArray_</span> <span class='layout'>(</span><span class='varid'>l</span><span class='layout'>,</span><span class='varid'>u</span><span class='layout'>)</span> <span class='varid'>bodyScale</span> <span class='comment'>-- bytes </span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span>     <span class='comment'>{-# INLINE newArray_ #-}</span>
<span class='varop'>&gt;</span>     <span class='varid'>newArray_</span> <span class='varid'>bounds</span> <span class='keyglyph'>=</span> <span class='varid'>newArray</span> <span class='varid'>bounds</span> <span class='layout'>(</span><span class='conid'>B</span> <span class='layout'>(</span><span class='conid'>V</span> <span class='num'>0</span> <span class='num'>0</span> <span class='num'>0</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>V</span> <span class='num'>0</span> <span class='num'>0</span> <span class='num'>0</span><span class='layout'>)</span> <span class='num'>1</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>     
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span>     <span class='comment'>{-# INLINE unsafeRead #-}</span>
<span class='varop'>&gt;</span>     <span class='varid'>unsafeRead</span> <span class='layout'>(</span><span class='conid'>STUArray</span> <span class='keyword'>_</span> <span class='keyword'>_</span> <span class='keyword'>_</span> <span class='varid'>arr</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>I</span><span class='cpp'>#</span> <span class='varid'>i</span><span class='layout'>)</span> <span class='keyglyph'>=</span> <span class='conid'>ST</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>s1</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>let</span> <span class='varid'>j</span> <span class='keyglyph'>=</span> <span class='varid'>bodyScale</span> <span class='varid'>i</span> <span class='keyword'>in</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>readDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='varid'>j</span>         <span class='varid'>s1</span> <span class='keyword'>of</span> <span class='layout'>{</span> <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s2</span><span class='layout'>,</span> <span class='varid'>xd</span>    <span class='cpp'>#</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>readDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>1</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>s2</span> <span class='keyword'>of</span> <span class='layout'>{</span> <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s3</span><span class='layout'>,</span> <span class='varid'>yd</span>    <span class='cpp'>#</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>readDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>2</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>s3</span> <span class='keyword'>of</span> <span class='layout'>{</span> <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s4</span><span class='layout'>,</span> <span class='varid'>zd</span>    <span class='cpp'>#</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>readDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>3</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>s4</span> <span class='keyword'>of</span> <span class='layout'>{</span> <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s5</span><span class='layout'>,</span> <span class='varid'>vxd</span>   <span class='cpp'>#</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>readDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>4</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>s5</span> <span class='keyword'>of</span> <span class='layout'>{</span> <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s6</span><span class='layout'>,</span> <span class='varid'>vyd</span>   <span class='cpp'>#</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>readDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>5</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>s6</span> <span class='keyword'>of</span> <span class='layout'>{</span> <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s7</span><span class='layout'>,</span> <span class='varid'>vzd</span>   <span class='cpp'>#</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>readDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>6</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>s7</span> <span class='keyword'>of</span> <span class='layout'>{</span> <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s8</span><span class='layout'>,</span> <span class='varid'>massd</span> <span class='cpp'>#</span><span class='layout'>)</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s8</span><span class='layout'>,</span> <span class='conid'>B</span> <span class='layout'>{</span> <span class='varid'>pos</span>    <span class='keyglyph'>=</span> <span class='conid'>V</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>xd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>yd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>zd</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>                     <span class='layout'>,</span> <span class='varid'>vel</span>    <span class='keyglyph'>=</span> <span class='conid'>V</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>vxd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>vyd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>vzd</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>                     <span class='layout'>,</span> <span class='varid'>mass</span> <span class='keyglyph'>=</span> <span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>massd</span> <span class='layout'>}</span> <span class='cpp'>#</span><span class='layout'>)</span> <span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span>
<span class='varop'>&gt;</span> 
<span class='varop'>&gt;</span>     <span class='comment'>{-# INLINE unsafeWrite #-}</span>
<span class='varop'>&gt;</span>     <span class='varid'>unsafeWrite</span> <span class='layout'>(</span><span class='conid'>STUArray</span> <span class='keyword'>_</span> <span class='keyword'>_</span> <span class='keyword'>_</span> <span class='varid'>arr</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>I</span><span class='cpp'>#</span> <span class='varid'>i</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>                 <span class='layout'>(</span><span class='conid'>B</span> <span class='layout'>(</span><span class='conid'>V</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>xd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>yd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>zd</span><span class='layout'>)</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>V</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>vxd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>vyd</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>vzd</span><span class='layout'>)</span><span class='layout'>)</span> <span class='layout'>(</span><span class='conid'>D</span><span class='cpp'>#</span> <span class='varid'>massd</span><span class='layout'>)</span><span class='layout'>)</span>
<span class='varop'>&gt;</span>         <span class='keyglyph'>=</span> <span class='conid'>ST</span> <span class='varop'>$</span> <span class='keyglyph'>\</span><span class='varid'>s1</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>let</span> <span class='varid'>j</span> <span class='keyglyph'>=</span> <span class='varid'>bodyScale</span> <span class='varid'>i</span> <span class='keyword'>in</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>writeDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='varid'>j</span>          <span class='varid'>xd</span>   <span class='varid'>s1</span>  <span class='keyword'>of</span> <span class='layout'>{</span><span class='varid'>s2</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>writeDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>1</span><span class='cpp'>#</span><span class='layout'>)</span>  <span class='varid'>yd</span>   <span class='varid'>s2</span>  <span class='keyword'>of</span> <span class='layout'>{</span><span class='varid'>s3</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>writeDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>2</span><span class='cpp'>#</span><span class='layout'>)</span>  <span class='varid'>zd</span>   <span class='varid'>s3</span>  <span class='keyword'>of</span> <span class='layout'>{</span><span class='varid'>s4</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>writeDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>3</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>vxd</span>   <span class='varid'>s4</span>  <span class='keyword'>of</span> <span class='layout'>{</span><span class='varid'>s5</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>writeDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>4</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>vyd</span>   <span class='varid'>s5</span>  <span class='keyword'>of</span> <span class='layout'>{</span><span class='varid'>s6</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>writeDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>5</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>vzd</span>   <span class='varid'>s6</span>  <span class='keyword'>of</span> <span class='layout'>{</span><span class='varid'>s7</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='keyword'>case</span> <span class='varid'>writeDoubleArray</span><span class='cpp'>#</span> <span class='varid'>arr</span> <span class='layout'>(</span><span class='varid'>j</span> <span class='varop'>+#</span> <span class='num'>6</span><span class='cpp'>#</span><span class='layout'>)</span> <span class='varid'>massd</span> <span class='varid'>s7</span>  <span class='keyword'>of</span> <span class='layout'>{</span><span class='varid'>s8</span> <span class='keyglyph'>-&gt;</span>
<span class='varop'>&gt;</span>         <span class='layout'>(</span><span class='cpp'>#</span> <span class='varid'>s8</span><span class='layout'>,</span> <span class='conid'>()</span> <span class='cpp'>#</span><span class='layout'>)</span> <span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span><span class='layout'>}</span>
<span class='varop'>&gt;</span> </pre>
]]>
        

    </content>
</entry>

<entry>
    <title>Software lockdown!</title>
    <link rel="alternate" type="text/html" href="http://axman6.homeip.net/blog/2009/01/software-lockdown.html" />
    <id>tag:axman6.homeip.net,2009:/blog//1.17</id>

    <published>2009-01-29T02:11:44Z</published>
    <updated>2009-01-29T02:43:56Z</updated>

    <summary>The things I&apos;ve bought are usually pretty cheap, and that makes me *want* to buy them, I *want* to help the developer and reward them for making something which is useful to me, and reasonably priced, or even a bargain.</summary>
    <author>
        <name>Alex Mason</name>
        <uri>http://axman6.homeip.net/</uri>
    </author>
    
        <category term="Software" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="software" label="Software" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="licencing" label="licencing" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://axman6.homeip.net/blog/">
        <![CDATA[<p>I've just read <a href="http://www.cimgf.com/">Marcus S. Zarra's</a> post about <a href="http://www.cimgf.com/2009/01/28/dont-treat-your-customers-like-thieves/">software licencing, piracy and stupidity</a> (to paraphrase), and I think he's hit the nail right on the head.</p>

<p>Treating potential customers like potential thieves makes them feel more inclined to follow these feeling. I'll admit that I've pirated software, but I've also bought a lot of it too. The stuff I've pirated is uaually something that I feel is far overpriced for what they offer. Like Marcus says, software is something you make once, and sell thousands of times; it's making money from nothing. The things I've bought are usually pretty cheap, and that makes me <em>want</em> to buy them, I <em>want</em> to help the developer and reward them for making something which is useful to me, and reasonably priced, or even a bargain.</p>

<p>I do not like being forced to buy your software. I do not like being forced to buy your software to use it for something that is useful, but not exactly (or at all) worth paying $30 for. Nor do I like being told that I have not bought your software. Give me the full thing to try, without restrictions, at all, give me a month and see if I feel I need it. If after that month, (and that's a month of use, not a month from the date of download), I feel I need your software, then I will buy it. If I never hit that month, then no, I will not be buying it, it has not been useful enough for me to consider it. Doesn't mean it's not great, or that it's buggy and annoying (I will tell you if it is), it just means I have no ude for it.</p>

<p>I'll take an example, VMware Fusion. Now, this is made by a very large company, a big, corporate business, that makes expensive software for some rather important tasks. But what happened when Fusion v2.0 came out? they gave it to us for free! I, and I'm sure many others would have paid for this update, they did a lot of work for it, added some very nice new features. But instead of them saying "hey! they're getting new stuff, they HAVE to pay!", they seemed to take the stance that these new features were missing features, and that v2.0 was heading towards making the program more complete, rather than expanding it.</p>

<p>This is an excellent example of how I feel software licencing should work. Be nice to your customers, give them treats, and they will do more than stay quiet about your products, they will tell their friends, or anyone they know who might be interested. They feel an affinity with you and your software, and will go the point of arguing and fighting over which is better, your product, or someone else's. Loyalty will always bring you more than fear, and being nice will bight you in the arse far less often than being a dick.</p>

<p>I don't think I have summed this up as well as Marcus managed to (I've just written this from start to finish, and can't be bothered to re-read it [pan's labyrinth awaits]), but I did feel like showing my support for his views, because he got how I feel so right.</p>

<p>Anyway, more later</p>

<p>~ Axman</p>
]]>
        

    </content>
</entry>

</feed>
