<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:cs_lectures</id>
  <title>lectures in computer science</title>
  <subtitle>lectures in computer science</subtitle>
  <author>
    <name>lectures in computer science</name>
  </author>
  <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/"/>
  <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom"/>
  <updated>2008-06-14T21:13:39Z</updated>
  <lj:journal username="cs_lectures" type="community"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://community.livejournal.com/cs_lectures/data/atom" title="lectures in computer science"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:5985</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/5985.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=5985"/>
    <title>Lazy Evaluation: an optimization technique</title>
    <published>2006-04-19T22:48:49Z</published>
    <updated>2006-04-19T22:48:49Z</updated>
    <content type="html">&lt;a name="cutid1"&gt;&lt;/a&gt;Imagine for a moment that you have an object that you can ask a particular question about, but the question is expensive to determine the answer to.  Sometimes you need the answer a lot, sometimes you never need the answer.  There are several ways to go about this; the simplest can be called "reactive" and "proactive".&lt;br /&gt;&lt;br /&gt;To show this, I'm going to need an object with an expensive question, so here's a heavily stripped down 3D vector in C++, with a method that returns the length of the vector:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Vector3D {
private:
  double x, y, z;

public:
  Vector3D(double new_x, double new_y, double new_z) {
    x = new_x;
    y = new_y;
    z = new_z;
  }

  void setX(double new_x) {x = new_x;}
  void setY(double new_y) {y = new_y;}
  void setZ(double new_z) {z = new_z;}
  double getX() {return x;}
  double getY() {return y;}
  double getZ() {return z;}

  double getLength() const {
    return sqrt(x*x + y*y + z*z);
  }
};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is a reactive design: the length is recalculated from scratch each time it gets asked for.  This is just fine most of the time, but sometimes you find that the length is asked for repeatedly between changes.  Since the method is expensive (well, okay, this one really isn't, but for our purposes we will call it so), we don't want to have to recalculate it each time it gets asked for.  So instead, let's try getting it to change every time something is changed.  This is called proactive design: the question is answered before it is asked.  Here's how that would work (added changed sections are in &lt;b&gt;bold&lt;/b&gt;):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Vector3D {
private:
  double x, y, z&lt;b&gt;, length&lt;/b&gt;;
  
&lt;b&gt;  void recalcLength() {
    length = return sqrt(x*x + y*y + z*z);
  }&lt;/b&gt;

public:
  Vector3D(double new_x, double new_y, double new_z) {
    x = new_x;
    y = new_y;
    z = new_z;
&lt;b&gt;    recalcLength();&lt;/b&gt;
  }

  void setX(double new_x) {
    x = new_x;
&lt;b&gt;    recalcLength();&lt;/b&gt;
  }
  
  void setY(double new_y) {
    y = new_y;
&lt;b&gt;    recalcLength();&lt;/b&gt;
  }
  
  void setZ(double new_z) {
    z = new_z;
&lt;b&gt;    recalcLength();&lt;/b&gt;
  }
  
  double getX() {return x;}
  double getY() {return y;}
  double getZ() {return z;}

  double getLength() const {
&lt;b&gt;    return length;&lt;/b&gt;  
  }
};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This isn't too bad either for most situations, you find; however, you now have a different problem: sometimes you call setX etc a lot of times on an object, but never ask for its length!  This is a lot of wasted effort to update something that never gets looked at.&lt;br /&gt;&lt;br /&gt;So what do you do?  Neither calculating from scratch every time it gets asked for nor recalculating whenever it changes gives acceptable performance.  You can't win.&lt;br /&gt;&lt;br /&gt;Or can you?&lt;br /&gt;&lt;br /&gt;What if you instead calculate the answer only when it needs to be calculated, and hold on to it for when you need it again?  You'd need to be able to tell when the answer is valid, and when you need to recalculate it...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Vector3D {
private:
  double x, y, z, length;
&lt;b&gt;  bool length_is_valid;&lt;/b&gt;
  
  void recalcLength() {
    length = return sqrt(x*x + y*y + z*z);
&lt;b&gt;    length_is_valid = true;&lt;/b&gt;
  }
public:
  Vector3D(double new_x, double new_y, double new_z) {
    x = new_x;
    y = new_y;
    z = new_z;
&lt;b&gt;    length_is_valid = false;&lt;/b&gt;
  }

  void setX(double new_x) {
    x = new_x;
&lt;b&gt;    length_is_valid = false;&lt;/b&gt;
  }
  
  void setY(double new_y) {
    y = new_y;
&lt;b&gt;    length_is_valid = false;&lt;/b&gt;
  }
  
  void setZ(double new_z) {
    z = new_z;
&lt;b&gt;    length_is_valid = false;&lt;/b&gt;
  }
  
  double getX() {return x;}
  double getY() {return y;}
  double getZ() {return z;}

  double getLength() {
&lt;b&gt;    if (!length_is_valid)
      recalcLength();&lt;/b&gt;
    return length;
  }
};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, we have three ways of designing our object to get the answer to the question.  Let's try using them.&lt;br /&gt;&lt;br /&gt;This table compares Reactive, Proactive, and Lazy evaluation methods by the number of times the evaluation happens, over the same sequence of test calls.  The test calls are Initialization, Querying, and Changing, which correspond to the methods Vector3D, getLength, and setX (or setY, or setZ), respectively.  There is an X in a cell if the answer is calculated during that row's call under that column's design.  At the bottom is the number of times the answer is calculated for that design.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;R&lt;/td&gt;&lt;td&gt;P&lt;/td&gt;&lt;td&gt;L&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;I&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the lazy evaluation beats them both.&lt;br /&gt;&lt;br /&gt;Now, you can't always use lazy evaluation.  It requires that you have absolute control over the data the question is based on - if something that your question depends on is directly accessible from something other than your object's set methods, you can't use it.  It also requires that the method that embodies the question is allowed to write to the object as opposed to simply read from it - unlike reactive and proactive evaluation, the question method cannot be const.  Then there are places where it's not appropriate - an inexpensive calculation doesn't gain much from lazy evaluation; sometimes it's better to have consistently timed responses than high speed most of the time and a relatively epic slog when it needs recalculating; it adds data to the object as a whole, which makes them cost more memory and which can also prevent libraries that copy large chunks of data to somewhere else (OpenGL, for instance) from operating efficiently.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:5842</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/5842.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=5842"/>
    <title>3D Graphics Primer, Part III: Projective Space, and Canonical Coordinates</title>
    <published>2006-02-26T15:38:34Z</published>
    <updated>2006-02-26T15:38:34Z</updated>
    <content type="html">So what's this fourth coordinate do for us?  We're still in a 3D world, aren't we?  So if we added a fourth coordinate, we'd start having things overlap.  This leads to the question: is there a way to get a canonical version of a 4-vector?&lt;br /&gt;&lt;br /&gt;Before we can really talk about this, I need to prove something to you.&lt;br /&gt;&lt;br /&gt;Consider the situation where we multiply a vector &lt;b&gt;v&lt;/b&gt; by a scalar n and then transform this new vector by a matrix &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;.  Can we express the transformed new vector in terms of the transformed old vector?&lt;br /&gt;&lt;br /&gt;Let\'s apply the matrix &amp;times vector operation (&lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;b&gt;v&lt;/b&gt;)&lt;sub&gt;j&lt;/sub&gt; = &amp;Sigma&lt;sub&gt;k&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt;&amp;times&lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;sub&gt;j&lt;/sub&gt;&lt;sub&gt;k&lt;/sub&gt; to a scaled vector (&lt;b&gt;v&lt;/b&gt; &amp;times; n)&lt;sub&gt;k&lt;/sub&gt; = &lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt; &amp;times; n:&lt;br /&gt;&lt;br /&gt;(&lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt; &amp;times; (&lt;b&gt;v&lt;/b&gt; &amp;times; n))&lt;sub&gt;j&lt;/sub&gt; = &amp;Sigma&lt;sub&gt;k&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt; &amp;times; n &amp;times; &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;sub&gt;j&lt;/sub&gt;&lt;sub&gt;k&lt;/sub&gt;&lt;br /&gt;= n &amp;times; &amp;Sigma&lt;sub&gt;k&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt; &amp;times; &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;sub&gt;j&lt;/sub&gt;&lt;sub&gt;k&lt;/sub&gt;&lt;br /&gt;= n &amp;times; (&lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt; &amp;times; &lt;b&gt;v&lt;/b&gt;)&lt;br /&gt;&lt;br /&gt;So, in short: the size of a vector doesn't change the way a matrix affects the vector's direction.&lt;br /&gt;&lt;br /&gt;It's pretty obvious that w only affects translation - the only part of the 4&amp;times;4 matrix that allows w to affect the outcome is the last column, which is where translation comes into play.  So in order to find out what 4-vectors correspond to each other, we will try to figure out how to convince a translation matrix to turn a particular vector &lt;b&gt;v&lt;/b&gt; to &amp;lt;0, 0, 0, w&amp;gt;.&lt;br /&gt;&lt;br /&gt;This isn't even vaguely hard:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;-&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;x&lt;/sub&gt;/&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;w&lt;/sub&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;-&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;y&lt;/sub&gt;/&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;w&lt;/sub&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;-&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;z&lt;/sub&gt;/&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;w&lt;/sub&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;...which also happens to affect  the vector &amp;lt;x/w, y/w, z/w, 1&amp;gt; in exactly the same way as it does &amp;lt;x, y, z, w&amp;gt;.&lt;br /&gt;&lt;br /&gt;So, in short:  &lt;b&gt;In all cases where w &amp;ne; 0, the canonical version of a 4-vector &lt;b&gt;v&lt;/b&gt; is &lt;b&gt;v&lt;/b&gt;/w.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;But what happens when w = 0?  Translation doesn't affect these at all, and we can't get a canonical version of it using the normal formula.&lt;br /&gt;&lt;br /&gt;Well, where can I put a point so that translation doesn't affect it at all?&lt;br /&gt;&lt;br /&gt;How about infinity?  After all, infinity plus any number is still infinity.  Space with an additional area for things at infinity is known as &lt;i&gt;projective space&lt;/i&gt;, and it has some strange properties.  For instance, parallel lines meet twice at infinity, once in one direction and once in the opposite direction.  The only property we're really concerned with is the fact that the area at infinity exists, and that it has one fewer dimension than the normal sections of space - so a 3-space turned projective has a plane at infinity.&lt;br /&gt;&lt;br /&gt;But that still leaves us with a problem: the chunk of space that can be called "infinity" has only two dimensions (you can think of them as, for instance, latitude and longitude), but we've got three dimensions to our vectors that talk about this chunk.  Fortunately we can use our multiplication result from before to come up with a canonical version of vectors with w = 0, choosing our canonical version to have a length of 1:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;v&lt;/b&gt;' = &lt;b&gt;v&lt;/b&gt; / ||&lt;b&gt;v&lt;/b&gt;||&lt;br /&gt;&lt;br /&gt;Next time: The Orthogonal Camera, Points, Lines.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:5598</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/5598.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=5598"/>
    <title>A 3D Graphics Primer, Part II: Common Transformations and The Fourth Coordinate</title>
    <published>2006-02-12T07:14:28Z</published>
    <updated>2006-02-12T07:21:39Z</updated>
    <content type="html">Now that we have our tools, let's see how to apply them.&lt;br /&gt;&lt;br /&gt;This is a scaling matrix:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;4&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;When applied to a given vector, the vector will get bigger: twice as big in the X direction, three times as big in the Y direction, and four times as big in the Z direction.  I hope I don't have to tell you how it does this.  You can use any numbers in a scaling transformation.&lt;br /&gt;&lt;br /&gt;Rotation is a bit more tricky.  I'll start with the two-dimensional case, where things are rotated around the origin.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/rotation1.jpg" style="float: left"&gt;Here's two vectors being rotated counterclockwise by 53.13 degrees.  The starting positions are thin, and the ending positions are thick.  From this diagram we will figure out how to rotate things counterclockwise.&lt;br /&gt;&lt;br /&gt;To do this, we must figure out the various trigonometric values for the angle we're rotating:  sin(53.13deg) = 0.8; cos(53.13deg) = 0.6.&lt;br /&gt;&lt;br /&gt;Now we take these and figure out where each of them come in:&lt;br /&gt;for &lt;b&gt;x&lt;/b&gt;, 0.6 appears as the new x component, and 0.8 appears as the new y component.&lt;br /&gt;for &lt;b&gt;y&lt;/b&gt;, 0.6 appears as the new y component, and -0.8 appears as the new x component.&lt;br /&gt;&lt;br /&gt;So here's a matrix that rotates things around the origin by &amp;theta;:&lt;br /&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;cos(&amp;theta;)&lt;/td&gt;
    &lt;td&gt;-sin(&amp;theta;)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;sin(&amp;theta;)&lt;/td&gt;
    &lt;td&gt;cos(&amp;theta;)&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;We can then take this matrix, and extend it to three dimensions, making a matrix for rotating around each of the three primary axes x, y, and z respectively:&lt;br /&gt;&lt;table style="border-collapse: collapse; border: solid black 1px;"&gt;
  &lt;tr&gt;
    &lt;td style="border: solid black 1px;"&gt;&lt;table style="border-collapse: collapse"&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;1&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;-sin(&amp;theta;)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;sin(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;)&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;&lt;/td&gt;
    &lt;td style="border: solid black 1px;"&gt;&lt;table style="border-collapse: collapse"&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;sin(&amp;theta;)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;1&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;-sin(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;)&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;&lt;/td&gt;
    &lt;td style="border: solid black 1px;"&gt;&lt;table style="border-collapse: collapse"&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;-sin(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;sin(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;)&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;0&lt;/td&gt;
          &lt;td style="border: solid grey 1px;"&gt;1&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;(for the record, you might see these with the signs on the sin terms the other way around; those are clockwise rotations.  Both are valid, but make sure you know which ones you're using.)&lt;br /&gt;&lt;br /&gt;From here, it is now possible to create a matrix that will rotate around an arbitrary axis... but I don't really feel like stepping through four matrix multiplications and then a heinous simplification step to get there, so I'll just give you the result.&lt;br /&gt;&lt;br /&gt;&lt;table style="border-collapse: collapse;"&gt;
  &lt;tr&gt;
    &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;) + (1 - cos(&amp;theta;))x&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;
    &lt;td style="border: solid grey 1px;"&gt;(1 - cos(&amp;theta;))xy - (sin(&amp;theta;))z&lt;/td&gt;
    &lt;td style="border: solid grey 1px;"&gt;(1 - cos(&amp;theta;))xz + (sin(&amp;theta;))y&lt;/td&gt;  
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style="border: solid grey 1px;"&gt;(1 - cos(&amp;theta;))xy + (sin(&amp;theta;))z&lt;/td&gt;  
    &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;) + (1 - cos(&amp;theta;))y&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;
    &lt;td style="border: solid grey 1px;"&gt;(1 - cos(&amp;theta;))yz - (sin(&amp;theta;))x&lt;/td&gt;  
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style="border: solid grey 1px;"&gt;(1 - cos(&amp;theta;))xz - (sin(&amp;theta;))y&lt;/td&gt;  
    &lt;td style="border: solid grey 1px;"&gt;(1 - cos(&amp;theta;))yz + (sin(&amp;theta;))x&lt;/td&gt;  
    &lt;td style="border: solid grey 1px;"&gt;cos(&amp;theta;) + (1 - cos(&amp;theta;))z&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;And that's rotation.&lt;br /&gt;&lt;br /&gt;You may be staring at this at this point and wonder why the hell I haven't done translation yet, seeing as it looks like the easiest of the transformations to do.  And if you're really good you'll start to realize why: &lt;b&gt;matrices don't provide for the possibility of adding a constant to the vector it's being applied to&lt;/b&gt;.  So we're going to have to come up with a way to translate things.&lt;br /&gt;&lt;br /&gt;Enter the fourth coordinate. &lt;br /&gt;&lt;br /&gt;Earlier, when I said that things in 3-space were represented by 3-vectors, I lied.  usually they are represented by &lt;b&gt;4&lt;/b&gt;-vectors &amp;lt;x,y,z,w&amp;gt;, where w is called a "scaling factor".  For most purposes, w is set to 1; other values are possible, but are not used as often.  To go with our 4-vectors, we must have 4&amp;times;4 matrices.  This, finally, gives us the ability to represent translations.  Here's a translation matrix for 3D, to translate things by a 3-vector &lt;b&gt;v&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;x&lt;/sub&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;y&lt;/sub&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;z&lt;/sub&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;So the fourth column is how much w contributes to each new coordinate, and the fourth row describes how much each old coordinate contributes to the new w.  The fourth row never changes from what it is in the above matrix for most purposes.  To extend a 3-matrix to a 4-matrix, just put 0s in all the new cells except for &lt;span style="font-family: verdana arial sans;"&gt;A&lt;/span&gt;&lt;sub&gt;4&lt;/sub&gt;&lt;sub&gt;4&lt;/sub&gt;, which gets a 1.&lt;br /&gt;&lt;br /&gt;Next time: the consequences of the fourth coordinate.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:5239</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/5239.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=5239"/>
    <title>3D Graphics Primer, Part I: Vectors and Matrices</title>
    <published>2006-02-11T07:38:50Z</published>
    <updated>2006-02-11T18:39:41Z</updated>
    <content type="html">All points in 3D space can be represented by three numbers, the distance from three planes that are perpendicular to each other.  These three numbers are usually called x, y, and z, and they're usually written something like this: &amp;lt;x, y, z&amp;gt;.  This is called a vector.  A vector, when named, is displayed in bold, i.e. &lt;b&gt;v&lt;/b&gt;.  Vectors can have any number of components - the most common in graphics work are 2, 3, and 4 component vectors.  The fourth component, when it exists, is called w.  You can talk about an individual component of a vector like this: &lt;b&gt;v&lt;/b&gt;&lt;sub&gt;x&lt;/sub&gt; (the first component of vector &lt;b&gt;v&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Here's some things you can do with vectors:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;You can add two vectors: &lt;b&gt;(u + v)&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt; = &lt;b&gt;u&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt; + &lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt;.  This of course means you can also subtract them.&lt;br /&gt;  &lt;li&gt;You can multiply a vector by a scalar:(&lt;b&gt;v&lt;/b&gt; &amp;times; n)&lt;sub&gt;k&lt;/sub&gt; = &lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt; &amp;times; n.  You can also divide a vector by a scalar, and multiply a scalar by a vector.&lt;br /&gt;  &lt;li&gt;You can multiply two vectors together to get a scalar, using an operation called a dot product:  &lt;b&gt;u&lt;/b&gt;&amp;middot;&lt;b&gt;v&lt;/b&gt; = &amp;Sigma;&lt;sub&gt;k&lt;/sub&gt;&lt;b&gt;u&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt;.&lt;br /&gt;  &lt;li&gt;You can multiply two 3-vectors together to get a vector, using an operation called a cross product:  &lt;b&gt;u&lt;/b&gt;&amp;times;&lt;b&gt;v&lt;/b&gt; = &amp;lt;&lt;b&gt;u&lt;/b&gt;&lt;sub&gt;y&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;z&lt;/sub&gt; - &lt;b&gt;v&lt;/b&gt;&lt;sub&gt;y&lt;/sub&gt;&lt;b&gt;u&lt;/b&gt;&lt;sub&gt;z&lt;/sub&gt;, &lt;b&gt;u&lt;/b&gt;&lt;sub&gt;x&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;z&lt;/sub&gt; - &lt;b&gt;v&lt;/b&gt;&lt;sub&gt;x&lt;/sub&gt;&lt;b&gt;u&lt;/b&gt;&lt;sub&gt;z&lt;/sub&gt;, &lt;b&gt;u&lt;/b&gt;&lt;sub&gt;x&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;y&lt;/sub&gt; - &lt;b&gt;v&lt;/b&gt;&lt;sub&gt;x&lt;/sub&gt;&lt;b&gt;u&lt;/b&gt;&lt;sub&gt;y&lt;/sub&gt;&amp;gt;.  This can be generalized to other numbers of dimensions, with number_of_dimensions - 1 vectors being needed, but it is not common.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;In addition to being able to represent points, 3d graphics requires that we be able to move points around according to some rule  The mechanism for doing this is known as a matrix.  Matrices are square arrays of numbers which describe certain kinds of transformations easily.  They are generally denoted by a sans-serif capital letter: &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;, and are shown like this:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;This particular matrix is called the identity matrix, for reasons I'll get to in a minute.  You can address an individual element in the matrix as &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;sub&gt;j&lt;/sub&gt;&lt;sub&gt;k&lt;/sub&gt;, where j is the row the element is in, and k is the column, starting with the topmost or leftmost line as 1.   here are the most important things (for graphics) that you can do with a matrix:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;You can multiply a matrix by a vector, to get another vector: (&lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;b&gt;v&lt;/b&gt;)&lt;sub&gt;j&lt;/sub&gt; = &amp;Sigma&lt;sub&gt;k&lt;/sub&gt;&lt;b&gt;v&lt;/b&gt;&lt;sub&gt;k&lt;/sub&gt;&amp;times&lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;sub&gt;j&lt;/sub&gt;&lt;sub&gt;k&lt;/sub&gt;.  This is called applying a matrix to a vector, or transforming a vector by a matrix.&lt;br /&gt;  &lt;li&gt;You can multiply a matrix by another matrix, to get a third matrix: &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;span style="font-family: verdana, arial, sans;"&gt;B&lt;/span&gt;&lt;sub&gt;j&lt;/sub&gt;&lt;sub&gt;k&lt;/sub&gt; = &amp;Sigma&lt;sub&gt;i&lt;/sub&gt;&lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;&lt;sub&gt;j&lt;/sub&gt;&lt;sub&gt;i&lt;/sub&gt;&lt;span style="font-family: verdana, arial, sans;"&gt;B&lt;/span&gt;&lt;sub&gt;i&lt;/sub&gt;&lt;sub&gt;k&lt;/sub&gt;.  applying a product of two matrices to a vector is equivalent to applying the two original matrices to the vector in turn.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Applying the identity matrix &lt;span style="font-family: verdana, arial, sans;"&gt;I&lt;/span&gt; to a vector &lt;b&gt;v&lt;/b&gt; results in &lt;b&gt;v&lt;/b&gt;, and multiplying a matrix &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt; by the identity matrix results in &lt;span style="font-family: verdana, arial, sans;"&gt;A&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Next: common transformation matrices, and why something I said is a convenient lie.&lt;br /&gt;&lt;br /&gt;EDIT: fixed the subscript to iterate over for applying matrix to vector.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:4959</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/4959.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=4959"/>
    <title>Integer division and processor-specific operations</title>
    <published>2005-07-12T00:22:10Z</published>
    <updated>2005-07-12T01:49:14Z</updated>
    <content type="html">Integer division &lt;i&gt;a&lt;/i&gt;/&lt;i&gt;b&lt;/i&gt;, defined:&lt;br /&gt;&lt;br /&gt;For any two integers &lt;i&gt;a&lt;/i&gt; and &lt;i&gt;b&lt;/i&gt; &amp;gt; 0, there exist unique integers &lt;i&gt;q&lt;/i&gt; and 0 &amp;le; &lt;i&gt;r&lt;/i&gt; &amp;lt; &lt;i&gt;b&lt;/i&gt; such that &lt;i&gt;a&lt;/i&gt; = &lt;i&gt;q&lt;/i&gt; &amp;times; &lt;i&gt;b&lt;/i&gt; + &lt;i&gt;r&lt;/i&gt;.  For instance:&lt;br /&gt;&lt;br /&gt;&lt;table style="text-align: right"&gt;
  &lt;tr&gt;&lt;td&gt;&lt;i&gt;a&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;b&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;q&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;r&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;-10&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;-4&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;So far, decently simple.  &lt;i&gt;r&lt;/i&gt; is positive in all of these.&lt;br /&gt;&lt;br /&gt;So let's extend division, so that we can use &lt;i&gt;b&lt;/i&gt; &amp;lt; 0 as well:&lt;br /&gt;&lt;br /&gt;For any two integers &lt;i&gt;a&lt;/i&gt; and &lt;b&gt;&lt;i&gt;b&lt;/i&gt; &amp;ne; 0&lt;/b&gt;, there exist unique integers &lt;i&gt;q&lt;/i&gt; and &lt;b&gt;0 &amp;le; &lt;i&gt;r&lt;/i&gt; &amp;lt; |&lt;i&gt;b&lt;/i&gt;|&lt;/b&gt; such that &lt;i&gt;a&lt;/i&gt; = &lt;i&gt;q&lt;/i&gt; &amp;times; &lt;i&gt;b&lt;/i&gt; + &lt;i&gt;r&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;table style="text-align: right"&gt;
  &lt;tr&gt;&lt;td&gt;&lt;i&gt;a&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;b&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;q&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;r&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;-10&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;-4&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;-3&lt;/td&gt;&lt;td&gt;-3&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;-10&lt;/td&gt;&lt;td&gt;-3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Woohoo.  Definition of integer division we can use on computers, where nearly every number can be positive or negative.&lt;br /&gt;&lt;br /&gt;Except that many computers don't USE this definition.  Here's the one that my two machines (Mac G4, Pentium III) use:&lt;br /&gt;&lt;br /&gt;For any two integers &lt;i&gt;a&lt;/i&gt; and &lt;i&gt;b&lt;/i&gt; &amp;ne; 0, there exist unique integers &lt;i&gt;q&lt;/i&gt; and &lt;b&gt;&lt;i&gt;r&lt;/i&gt; &amp;isin [0,&lt;i&gt;b&lt;/i&gt;)&lt;/b&gt; such that &lt;i&gt;a&lt;/i&gt; = &lt;i&gt;q&lt;/i&gt; &amp;times; &lt;i&gt;b&lt;/i&gt; + &lt;i&gt;r&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;table style="text-align: right"&gt;
  &lt;tr&gt;&lt;td&gt;&lt;i&gt;a&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;b&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;q&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;r&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;-10&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;-4&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;-3&lt;/td&gt;&lt;td&gt;&lt;b&gt;-4&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;-2&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;-10&lt;/td&gt;&lt;td&gt;-3&lt;/td&gt;&lt;td&gt;&lt;b&gt;3&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;-1&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;In the former, and &lt;i&gt;r&lt;/i&gt; is always positive.  in the latter, &lt;i&gt;r&lt;/i&gt; gets its sign from &lt;i&gt;b&lt;/i&gt;.  Some computers still use the former, though, so not all computers divide the same way.&lt;br /&gt;&lt;br /&gt;Moral of the story:  when writing a program for multiple platforms, make sure you ALWAYS get the answer you intend on getting from division.  If this means hacking apart your numbers before or after you get them, so be it.&lt;br /&gt;&lt;br /&gt;EDIT: fixed the third table to correct signs for &lt;i&gt;q&lt;/i&gt; in the bottom two rows.&lt;br /&gt;EDIT AGAIN: fixed the third table again because I'm an idiot.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:4665</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/4665.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=4665"/>
    <title>Calling Functions, the Program Stack, and the Void data type</title>
    <published>2005-06-10T03:18:24Z</published>
    <updated>2005-06-10T03:18:24Z</updated>
    <content type="html">Computer programs aren't monolithic; they are composed of littler pieces of code known as functions. Each of these functions acts on its own, using its own data, and acting essentially like its own program.  And each function can call other functions, and each of those functions can act on its own.  But all this makes one wonder how the heck it does that.&lt;br /&gt;&lt;br /&gt;Enter the program stack.&lt;br /&gt;&lt;br /&gt;The program stack is basically a sequential area of memory - an array, almost, except that you can put anything in it (I'll explain how in a few moments) - used to store all the data that the program uses.  When you call a function, you increase the size of the stack, and when you return from a function, you decrease the size of the stack.&lt;br /&gt;&lt;br /&gt;This is the program stack before we make the function call.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/Stack1.gif"&gt;&lt;br /&gt;&lt;br /&gt;This is after we finish making the function call.  We have pushed a placeholder for the return value, and all the arguments, onto the stack.  We're now at the start of the function itself.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/Stack2.gif"&gt;&lt;br /&gt;&lt;br /&gt;Now, the function adds its own variables to the stack.  These are known as local variables.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/Stack3.gif"&gt;&lt;br /&gt;&lt;br /&gt;The function runs until it arrives at a return statement, at which point it pops all the stuff it has been using other than the return value off the stack.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/Stack4.gif"&gt;&lt;br /&gt;&lt;br /&gt;And that's how it works.&lt;br /&gt;&lt;br /&gt;"BUT WAIT!" you cry, confused.  "isn't an array supposed to hold the same thing, all the time?  You described it as an array earlier, and here we are stuffing everything from booleans to doubles in it!"&lt;br /&gt;&lt;br /&gt;And you would be right.  The program stack actually uses a special type, known to C programmers as "void*".  the void*, or void pointer, data type is special because any pointer can be turned into a void pointer, and any void pointer can be turned into a pointer of any other type.  A void pointer points at an object a single byte wide:  when we put things onto the program stack, we remember where they are as distance in bytes from the bottom of our portion of stack, which for each function is addressed as index 0 in the array.&lt;br /&gt;&lt;br /&gt;But how do we change the indexing of an array that already exists?  Remember that arrays are passed around as pointers.  In fact, we can use any pointer as if it were an array, including pointers we create by finding the location of a specific index of an array.  So all the function sees is a pointer to the bottom of its section of stack, and it knows where in the program stack to find the other things it needs, using an index into the 'array' created by the pointer to the function's section of stack.&lt;br /&gt;&lt;br /&gt;To summarize:&lt;br /&gt;&lt;br /&gt;Functions use a program stack to store their return values, arguments, and local variables.  When called, their return value placeholder and arguments are already there;when they return, they leave only the return value.  They see only their section of the program stack, through a void pointer acting as an array.  They know where to find their stuff on the program stack by using constant indices into that array.&lt;br /&gt;&lt;br /&gt;Have I confused you yet?&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:4495</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/4495.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=4495"/>
    <title>cs_lectures @ 2005-05-07T16:04:00</title>
    <published>2005-05-07T20:04:26Z</published>
    <updated>2005-05-07T20:04:26Z</updated>
    <content type="html">Going off of &lt;span class='ljuser' lj:user='derakon' style='white-space: nowrap;'&gt;&lt;a href='http://derakon.livejournal.com/profile'&gt;&lt;img src='http://p-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://derakon.livejournal.com/'&gt;&lt;b&gt;derakon&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;'s &lt;a href="http://www.livejournal.com/community/cs_lectures/766.html"&gt;entry about Gray Codes&lt;/a&gt;, here's how to generate the gray codes mentioned there (there are lots and lots and lots of gray codes, something like 120 million for 5-bit gray codes).&lt;br /&gt;&lt;br /&gt;The 1-bit sequence of gray codes is obviously (0,1).  To get the list of n-bit gray codes, you take the n-1-bit list, append its own reflection to itself, with the most significant bit turned on:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/graygenerator.gif"&gt;&lt;br /&gt;&lt;br /&gt;This kind of gray code is the most commonly used, and it's known as the Reflected Binary Gray Code.&lt;br /&gt;&lt;br /&gt;It's possible to go from a binary number to reflected binary gray code, and vice versa, using operations that work on one bit at a time.&lt;br /&gt;&lt;br /&gt;From Binary to Gray:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;start at the second least significant bit (the one that's worth 2).&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;If the bit we're looking at is on, change the state of the next less significant bit (so if we're on the bit that's worth 4, change the state of the bit that's worth 2).&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;move to the next more significant bit (if we're on 4, go to the one worth 8), and go back to step 2.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;So with 13 (0b1101) we get 1101 -&amp;gt; 1101 -&amp;gt; 1111 -&amp;gt; 1011.&lt;br /&gt;&lt;br /&gt;From Gray to Binary:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;start at the most significant bit&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;If the bit we're looking at is on, change the state of the next less significant bit.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;move to the next less significant bit, and if we're not on the least significant bit, go back to step 2.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;So with gray 13 (0b1011) we get 1011 -&amp;gt; 1111 -&amp;gt; 1101 -&amp;gt; 1101.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:4119</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/4119.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=4119"/>
    <title>Stacks, Queues, Doubly Linked Lists (old)</title>
    <published>2005-05-04T05:04:08Z</published>
    <updated>2005-05-04T05:04:08Z</updated>
    <content type="html">&lt;a name="cutid1"&gt;&lt;/a&gt;Before I actually get into stacks and queues, one of the comments on the last entry asked about doubly linked lists - where each list item knows not only where the next is, but where the previous one is:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/doublylinkedlist.gif"&gt;&lt;br /&gt;&lt;br /&gt;This has the advantage that we can 1. iterate backwards through the list (something that sometimes you need), 2. get to a specific item that's late in the list a lot faster , and 3. delete from the end of the list in constant time, so in effect we get a constant-time unrestricted deque (more on what that is later).&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid2"&gt;&lt;/a&gt;A very common use for data structures is for storage of things that we need a lot of together to work properly.  A good example of this is HTML; it takes a lot of tags to get an HTML page working properly, and a browser needs to consider each one in its context to deal with the whole.  The tool it uses to work its way through the file is known as a Stack, where you can hold data like you would a pack of cards: you can see the one on top, and you ccan put things on the top.  Often this is all you need.&lt;br /&gt;&lt;br /&gt;A stack is a data structure with four basic operations:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;b&gt;push&lt;/b&gt; &lt;i&gt;object&lt;/i&gt; will put the object onto the top of the stack, &lt;br /&gt;  &lt;li&gt;&lt;b&gt;pop&lt;/b&gt; will remove the topmost object from the stack,&lt;br /&gt;  &lt;li&gt;&lt;b&gt;peek&lt;/b&gt; will look at the topmost object on the stack (but will not change the stack),&lt;br /&gt;  &lt;li&gt;&lt;b&gt;length&lt;/b&gt; will tell you how many objects there are on a stack (but will not change the stack).&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;This table demonstrates the operation of a stack.  Peek and length are the values that those two operations would provide if run after the command.&lt;br /&gt;&lt;table border="1" style="border-collapse: collapse"&gt;
  &lt;tr&gt;&lt;td&gt;Command&lt;/td&gt;&lt;td&gt;Stack State&lt;/td&gt;&lt;td&gt;peek&lt;/td&gt;&lt;td&gt;length&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;(start)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;push a&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;push b&lt;/td&gt;&lt;td&gt;a b&lt;/td&gt;&lt;td&gt;b&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;pop&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;push c&lt;/td&gt;&lt;td&gt;a c&lt;/td&gt;&lt;td&gt;c&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;pop&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;pop&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;* peek can't return anything in these states because there's nothing to peek at.&lt;br /&gt;&lt;br /&gt;There are two basic ways to represent a stack using the base data structures we have: one is an array, and the other is a linked list.  Here's how we work in both of these, using st as the underlying data structure, and len as the length.&lt;br /&gt;&lt;br /&gt;&lt;table border="1" style="border-collapse: collapse"&gt;
  &lt;tr&gt;&lt;td&gt;Command&lt;/td&gt;&lt;td&gt;array implementation&lt;/td&gt;&lt;td&gt;list implementation&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;push object&lt;/td&gt;&lt;td&gt;st[len] = object;&lt;br&gt;len = len + 1;&lt;/td&gt;&lt;td&gt;st.insertAtStart(object);&lt;br&gt;len = len + 1;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;pop&lt;/td&gt;&lt;td&gt;len = len - 1;&lt;/td&gt;&lt;td&gt;st.removeFromStart();&lt;br&gt;len = len - 1;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;peek&lt;/td&gt;&lt;td&gt;return st[len - 1];&lt;/td&gt;&lt;td&gt;return st.firstObject;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;length&lt;/td&gt;&lt;td&gt;return len;&lt;/td&gt;&lt;td&gt;return len;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Arrays have the advantages that you never have to allocate any more memory to add something to the stack and that you never have to clean up after removing something from the stack (you just move the length down and leave the object there, where it will get overwritten when you push enough stuff in), and the disadvantage that you have to limit the size of the stack from the beginning.  Lists have the advantage that you can't run out of space on the stack (until you run out of memory on the computer entirely), but that it's slower since you have to allocate and deallocate memory as you add and remove things from the stack.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid3"&gt;&lt;/a&gt;A queue is similar to a stack, but it does things in a different order: peek and pop look at what (from the stack point of view) would be the bottom of the queue, not the top.  It's like the line at the store: the cashier only works with the first person in line, and when you get into the line you are the last person in line.  A queue is often used when you are recieving messages or something that have to be processed in the order they arrive.&lt;br /&gt;&lt;br /&gt;This table demonstrates the operation of a queue.  Peek and length are the values that those two operations would provide if run after the command.&lt;br /&gt;&lt;table border="1" style="border-collapse: collapse"&gt;
  &lt;tr&gt;&lt;td&gt;Command&lt;/td&gt;&lt;td&gt;Queue State&lt;/td&gt;&lt;td&gt;peek&lt;/td&gt;&lt;td&gt;length&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;(start)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;push a&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;push b&lt;/td&gt;&lt;td&gt;a b&lt;/td&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;pop&lt;/td&gt;&lt;td&gt;b&lt;/td&gt;&lt;td&gt;b&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;push c&lt;/td&gt;&lt;td&gt;b c&lt;/td&gt;&lt;td&gt;b&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;pop&lt;/td&gt;&lt;td&gt;c&lt;/td&gt;&lt;td&gt;c&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;pop&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;* peek can't return anything in these states because there's nothing to peek at.&lt;br /&gt;&lt;br /&gt;A queue cannot easily be implemented in a single array; it is possible to implement it using two stacks, but it is complicated and not often done, in particular because it has a tendency to do a lot of the work in spurts.&lt;br /&gt;&lt;br /&gt;Changing a linked stack into a queue involves replacing just the push() function with one that inserts at the end instead of the start.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:3994</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/3994.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=3994"/>
    <title>Linked Lists (old)</title>
    <published>2005-05-04T05:03:23Z</published>
    <updated>2005-05-04T05:03:23Z</updated>
    <content type="html">&lt;a name="cutid1"&gt;&lt;/a&gt;So our basic data structure, the one that is used a whole lot, is the array.  It has one primary advantage:  you can access any element in the array in constant time, and you don't have to think too much about pointers when you do.  Oh, and it is the most efficient storage technique in terms of memory usage.  But it also has disadvantages:  How do you insert an object into an array at a given point and have it shove all the other ones farther in?  How do you delete an object from an array and have all the other objects move up to fill the space left?&lt;br /&gt;&lt;br /&gt;All of these can be answered, but they take a considerable amount of time when you have a big array:  you have to actually use the move/copy commands that the memory may or may not provide, and in many cases the insertion needs to move the whole array because you've got stuff around the array that you don't want to step on - and since pointers to that array can be stored in many places, you're liable to break your program if you try that.&lt;br /&gt;&lt;br /&gt;So, instead, we invent a new data structure: a Linked List.&lt;br /&gt;&lt;br /&gt;A Linked List, instead of storing a lot of objects right next to each other, stores each individual object along with a pointer to the next object in the list, like this:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/linkedlist1.gif"&gt;&lt;br /&gt;&lt;br /&gt;That symbol over on the right that the last pointer's arrow ends in signifies that it is a &lt;i&gt;null pointer&lt;/i&gt; - basically the address in the pointer is 0, and the computer never lets you touch the stuff there, so that you can use the null pointer to say "there's nothing here".  The symbol itself comes from electronics, where it means that the wire goes to ground.  In our case, the null pointer means that we're at the end of the list.  &lt;br /&gt;&lt;br /&gt;So let's see how well this linked list works.  First, the random access test: can we get the &lt;i&gt;n&lt;/i&gt;th object in the list, and how long does it take?&lt;br /&gt;&lt;br /&gt;Well, to get the &lt;i&gt;n&lt;/i&gt;th object, we need to get the pointer to it... which is in the &lt;i&gt;n-1&lt;/i&gt;th object.  But we need to get the pointer to that, so we go to the &lt;i&gt;n-2&lt;/i&gt;th object... etc.  So random access takes linear time.  Suckage, right?  Wellllllll.... sorta.  The thing is that often when you deal with lots of data at once, you iterate through the array - get the 0th item, then the 1st, then the 2nd, then the 3rd, etc.  And with a linked list, this takes pretty much exactly as long as it would with an array: to get the next object, just follow the pointer from the current object.  So with a linked list, as with an array, iterating through the whole list takes linear time.&lt;br /&gt;&lt;br /&gt;Now, the insertion test: can we insert an object into the list at a specific point, and how long does it take?&lt;br /&gt;&lt;br /&gt;First we have to get there.  We know that this takes an amount of time equal to the number of nodes we have to pass through.  However, once we ARE there, it's very simple:  given the node we want to insert N, and the node that we want to have before it P, we do this:&lt;br /&gt;&lt;br /&gt;put N somewhere and assign the pointer FROM P to the pointer FROM N.&lt;br /&gt;assign the pointer TO N to the pointer FROM P.&lt;br /&gt;&lt;br /&gt;Like this:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/linkedlistinsert.gif"&gt;&lt;br /&gt;&lt;br /&gt;So, yes, it still takes linear time, but there's still several nice features: you never have to move the parts of the list you already have, and you can do it multiple times in linear time too (technically O(M+N) where M is the number of nodes you have to go through to get to the last node that you want to add one after and N is the number of nodes you want to insert).&lt;br /&gt;&lt;br /&gt;Thirdly, the deletion test: can we delete a specific object from the list and have the list still work, and how long does it take?&lt;br /&gt;&lt;br /&gt;And the answer is still yes, and like insertion it takes linear time for one or many.&lt;br /&gt;&lt;br /&gt;To delete a node D from a linked list, go again to the node before it (P), and change P's node from pointing at D to pointing at the thing D is pointing at.  Then we can safely free up the memory previously used by D.  Thus:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/linkedlistdelete.gif"&gt;&lt;br /&gt;&lt;br /&gt;Now that we've done the basics of linked lists, let's consider a common construction, where we store pointers to the first and last nodes on the list somewhere that we can access quickly.  How much work does it take to insert before the first node?  after the last one?  How long does it take to delete the first or last node?  In all cases we must maintain the pointers to first and last.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Inserting before the first object is done by setting the new object's pointer to that of the old first node and changing the "first" pointer to the location of the new first object.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Deleting the first object is done by setting the "first" pointer to that of the pointer from the first object, and freeing the memory used by the old first object.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Inserting after the last object is done by setting the old last object's pointer and the "last" pointer to the address of the new object.  The new object's pointer should be set to null.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Deleting the last object is a pain: you go through the entire list waiting for a pointer to the last object to show up (which it will in the second-to-last object), then changing "last" to the second-to-last object, changing the second-to-last object's pointer to null, and freeing the memory that the old last object took up.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;So inserting on either side is fine, and deleting the first object is fine, but deleting the last object takes linear time always.&lt;br /&gt;&lt;br /&gt;Next time:  Stacks and Queues.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:3701</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/3701.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=3701"/>
    <title>Let's talk data structures (old)</title>
    <published>2005-05-04T05:02:22Z</published>
    <updated>2005-05-04T05:02:22Z</updated>
    <content type="html">I want to discuss data structures - the things that computers use to store, collate, and find information in as efficient a way as possible - but to do so I have to talk about a few simple things first.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;b&gt;Memory&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Imagine, for a moment, that you have a giant-huge wall of dials, and a clerk that can read and operate these dials.  Each dial is numbered, and can store a number between 0 and 255, inclusive.  So you can ask the clerk to go to one of these dials (by telling him "tell me the value of the dial numbered 49,152"), and you can also ask the clerk to change the value of one of these dials (by telling him "change the value of the dial numbered 49,152 to 5"), and both of these things take the clerk one second.&lt;br /&gt;&lt;br /&gt;This approximately describes something known as Random Access Memory.  It is called "random access" because you can get information to or from any piece of memory at any time, and it always takes the same amount of time.&lt;br /&gt;&lt;br /&gt;The only real difference between what I described and actual RAM you have in your computer is that the dials are replaced with transistors, the clerk is replaced with a multiplexer, and it takes ten or less &lt;i&gt;nano&lt;/i&gt;seconds to do either of the above mentioned operations.  Actually there are few Really Special operations that can be pulled off with most memory, like moving or copying huge chunks of memory to other places, that go a lot faster than would usually be possible if you had to tell the memory each little tiny step.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid2"&gt;&lt;/a&gt;&lt;b&gt;Pointers&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So imagine that you do this:  you take the values of a consecutive pair of those dials - say, dials 1022 and 1023 - and put them together to get a single unique number.  Then, with that single number, you ask the clerk to go get the value of the dial with that number.  This is what's known as a pointer:  a piece of memory that is used to refer to another piece of memory.  So say that dial 1022 has the value 192, and that dial 1023 has the value 0.  To get our number we'll multiply the first number by 256 (because that's one bigger than the largest number we can store on a dial) and then add the second number:  192*256 + 0 = 49152.  Then we ask the clerk for the value of dial 49152, and he says "5" back to us.&lt;br /&gt;&lt;br /&gt;Pointers are represented in a lot of ways.  The most common is a box with an arrow leading out from the center of it pointing at another box:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/pointer.gif"&gt;&lt;br /&gt;&lt;br /&gt;So that the left box is the pointer, and the right box is what the pointer is pointing at.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid3"&gt;&lt;/a&gt;&lt;b&gt;Multi-byte data types&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Most of the time, one dial on the memory isn't enough to store any useful values; 0..255 can't store, for instance, any decent amount of money.  We saw this earlier with our pointer, which we defined as two bytes put next to each other.  Most modern computers actually store pointers as 4-byte (or 32-bit, which you've probably seen it described as) unsigned numbers.  Similarly, we can define other common data types like this, which is a list ganked from Java:&lt;br /&gt;&lt;br /&gt;bool: 1/8 of a byte (a bit, which can hold a single value of either 0 (false) or 1 (true)), will group together with other bools in the same record to fill out bytes efficiently.  no matter how many bools there are in a record, they will ALWAYS take up a whole number of bytes, to make life easier.&lt;br /&gt;byte: 1 byte, 2's complement if signed (defaults to signed)&lt;br /&gt;short: 2 bytes, 2's complement if signed (defaults to signed)&lt;br /&gt;int: 4 bytes, 2's complement if signed (defaults to signed)&lt;br /&gt;long: 8 bytes, 2's complement if signed (defaults to signed)&lt;br /&gt;char: 2 bytes, interpreted as UTF-16&lt;br /&gt;float: 4 bytes, interpreted as IEEE 754 "float" type&lt;br /&gt;double: 8 bytes, interpreted as IEEE 754 "double" type&lt;br /&gt;&lt;br /&gt;Each of these will be represented in graphics as a rectangle of appropriate size, in this and following posts.  Note that I won't necessarily use many of these types.  In those rare cases that I need a char, float, or double and need to distinguish them from the integral types of the same size, I will use a letter inside the rectangle to signify which I mean.&lt;br /&gt;&lt;br /&gt;When I say something is "a pointer to an int", for instance, what I mean is that when you follow the pointer, get not only the byte that it points at directly, but get enough bytes after it so that you have 4 bytes.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid4"&gt;&lt;/a&gt;&lt;b&gt;Structured Data&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Most applications need to keep data together - names with addresses, account numbers with dollar figures, etc.  Structured data does this.  By putting together a lot of littler types of data, you can create a larger piece of data that can be talked about via a pointer all at once, by using a lookup table.&lt;br /&gt;&lt;br /&gt;So we could have a structure that we define like this (in C++ish):&lt;br /&gt;&lt;pre&gt;struct a_struct {
  byte a,
  byte b,
  short c,
  int d,
  long e
};&lt;/pre&gt;&lt;br /&gt;So it looks like this:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://vorn.dyndns.org/~vorn/struct.gif"&gt;&lt;br /&gt;&lt;br /&gt;and we can point at an entire structure by pointing at the first byte in the structure.  Then we can just add a number to that pointer to get a pointer to any attribute of the struct: 0 for a, 1 for b, 2 for c, 4 for d, 8 for e.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid5"&gt;&lt;/a&gt;&lt;b&gt;Arrays&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;An array is a special kind of structured data, in that all the objects in it are the same type.  This also means that they are all the same size, which makes it a lot easier to look up an object in an array - we don't have to store a lookup table, we can just multiply.  An array is thrown around in programs as a pointer to the start of the array.  Encoded into the program is the kind (and thus the size) of data.  Often included along with the array is the total size of the array (but not in C/C++!)&lt;br /&gt;&lt;br /&gt;An object in an array is referred to by its index, or location in the array.  Most languages (notable exceptions are SQL and VB) start indexing at 0, so that the first object in the array has an index of 0.  To get a pointer to an object in an array by its index:&lt;br /&gt;&lt;br /&gt;p = pointer to the array as a whole&lt;br /&gt;s = size of the objects stored in the array&lt;br /&gt;i = index that you want to point at&lt;br /&gt;&lt;br /&gt;objectpointer = p + s * i&lt;br /&gt;&lt;br /&gt;It's really that simple.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:3431</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/3431.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=3431"/>
    <title>Heap Sort and Priority Queues (old)</title>
    <published>2005-05-04T04:58:15Z</published>
    <updated>2005-05-04T04:58:15Z</updated>
    <content type="html">in my last post I mentioned a data structure called a Priority Queue.  It turns out that one of my friends wants to implement Dijkstra's Algorithm, and was totally lost on this structure.  So, here's how it's done.  Or, rather, one way.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;The way we're going to do this is through a common data structure called a &lt;i&gt;heap&lt;/i&gt;, which is basically an array that sorts itself out partially when you add or remove a piece of data from it.  Note that I said "partially" - the order that a heap imposes is not total, it is just enough to get by for what it's doing.  How much sorting does it do, exactly?  Well, it's like this.&lt;br /&gt;&lt;br /&gt;A heap is an array arrenged in such a way such that for every index k, the numbers at indices 2k + 1 and 2k + 2, if they exist, are both greater than (or less than, for a maxheap) the number at index k.  This may not sound like much ordering, at first, but this is actually the simplest of several equivalent metrics for ordering things.  The most significant and telling of these metrics is that &lt;b&gt;every possible path through the packed binary tree that the heap represents, from the root of the tree to any leaf, is always in the correct order&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;"But wait!" you say.  "What are all these paths?"  Well, here's the 8 paths through a 15-node packed binary tree, as indices:&lt;br /&gt;&lt;br /&gt;0 1 3 7&lt;br /&gt;0 1 3 8&lt;br /&gt;0 1 4 9&lt;br /&gt;0 1 4 10&lt;br /&gt;0 2 5 11&lt;br /&gt;0 2 5 12&lt;br /&gt;0 2 6 13&lt;br /&gt;0 2 6 14&lt;br /&gt;&lt;br /&gt;You can say "oh, shiny" now.&lt;br /&gt;&lt;br /&gt;So all of these paths, once all the heap's sorting is done, are in order.  So how does it know when to sort these things so that things stay that way even through a flurry of insertions and deletions?  Well, let's watch one in action.  Let's take the data [50, 65, 2, 80, 57, 1, 7, 95, 53, 56] and turn it into a heap.&lt;br /&gt;&lt;br /&gt;This is representable as five paths of varying length:&lt;br /&gt;&lt;br /&gt;50 65 80 95&lt;br /&gt;50 65 80 53&lt;br /&gt;50 65 57 56&lt;br /&gt;50 2 1&lt;br /&gt;50 2 7&lt;br /&gt;&lt;br /&gt;These are obviously not in order, so let's go through them to make them that way.  We'll start at the 57, because it's the last actual node with leaves attached, and we will swap the root of each trio of numbers with the smallest of that trio:&lt;br /&gt;&lt;br /&gt;57: 56&lt;br /&gt;&lt;br /&gt;Since 56 is the smallest in this group of numbers, we swap it with the parent:&lt;br /&gt;&lt;br /&gt;56: 57.&lt;br /&gt;&lt;br /&gt;And then we look at where the 57 is now, and see that it has no leaves anymore, so obviously it's the smallest of those three.  We know that the parent of the 56 will be checked later, so we'll leave it there for a while.  Next:&lt;br /&gt;&lt;br /&gt;80: 95, 53 -&amp;gt; 53: 95, 80&lt;br /&gt;&lt;br /&gt;the 95 hasn't moved, and we've already technically checked it (we know it's sorted because it has no leaves) we're not going to look at it.  the 80 now also has no leaves, so it is sorted.  Finally, the area above will be checked later.  Next:&lt;br /&gt;&lt;br /&gt;2: 1 7 -&amp;gt; 1: 2 7&lt;br /&gt;&lt;br /&gt;Both 2 and 7 are leaves, so we'll go on.&lt;br /&gt;&lt;br /&gt;65: 53, 56 -&amp;gt; 53: 65, 56&lt;br /&gt;&lt;br /&gt;The 56 hasn't moved, but the 53 and 65 have!  We have to look at the 65 again and see whether we need to swap...&lt;br /&gt;&lt;br /&gt;65: 95, 80&lt;br /&gt;&lt;br /&gt;Nope.  Next:&lt;br /&gt;&lt;br /&gt;50: 53, 1 -&amp;gt; 1: 53, 50&lt;br /&gt;&lt;br /&gt;In a few steps we've managed to move the 1 to the root of the tree.  However, there's a bit more to do: the 50 there has moved, so let's check its children:&lt;br /&gt;&lt;br /&gt;50: 2, 7 -&amp;gt; 2: 50, 7&lt;br /&gt;&lt;br /&gt;The 50 is a leaf, so we don't check further along there.&lt;br /&gt;&lt;br /&gt;Now we have completed the heap sort, and these are the results:&lt;br /&gt;&lt;br /&gt;1 53 2 65 56 50 7 95 80 57&lt;br /&gt;&lt;br /&gt;Which leaves the five paths as:&lt;br /&gt;&lt;br /&gt;1 53 65 95&lt;br /&gt;1 53 65 80&lt;br /&gt;1 53 56 57&lt;br /&gt;1 2 50&lt;br /&gt;1 2 7&lt;br /&gt;&lt;br /&gt;As you can see, all 5 paths are sorted, which was our original goal.  So now that we have that, let's add a number to it: 44.  44 will appear just after the 57 at the start, adding one more path:&lt;br /&gt;&lt;br /&gt;1 53 65 95&lt;br /&gt;1 53 65 80&lt;br /&gt;1 53 56 57&lt;br /&gt;1 53 56 44&lt;br /&gt;1 2 50&lt;br /&gt;1 2 7&lt;br /&gt;&lt;br /&gt;So now we check 44's parent (because we know that that section has changed):&lt;br /&gt;&lt;br /&gt;56: 57 44 -&amp;gt; 44: 57 56&lt;br /&gt;&lt;br /&gt;And then we check the 56's position now and see it's a leaf, and then we go up to 44's parent:&lt;br /&gt;&lt;br /&gt;53: 65 44 -&amp;gt; 44: 65 53&lt;br /&gt;&lt;br /&gt;And we check 53 because it moved:&lt;br /&gt;&lt;br /&gt;53: 56 57&lt;br /&gt;&lt;br /&gt;and we check 44's parent now:&lt;br /&gt;&lt;br /&gt;1: 44 2&lt;br /&gt;&lt;br /&gt;and that's fine too, so we're all done shoveling stuff to add the 44 in there.&lt;br /&gt;&lt;br /&gt;Our new array:&lt;br /&gt;&lt;br /&gt;1 44 2 65 53 50 7 95 80 56 57&lt;br /&gt;&lt;br /&gt;And the paths:&lt;br /&gt;&lt;br /&gt;1 44 65 95&lt;br /&gt;1 44 65 80&lt;br /&gt;1 44 53 56&lt;br /&gt;1 44 53 57&lt;br /&gt;1 2 50&lt;br /&gt;1 2 7&lt;br /&gt;&lt;br /&gt;Which are all sorted.  So now let's try removing that first number there, because it's the only one we can absolutely guarantee the relative value of (since it's the lowest number on all the paths, it's the lowest number on the whole array)&lt;br /&gt;&lt;br /&gt;__ 44 2 65 53 50 7 95 80 56 57&lt;br /&gt;&lt;br /&gt;We need a new number to put there!  Shoving the whole array over won't work because then none of the paths will be valid at all anymore.  So let's instead take the last item and make it first:&lt;br /&gt;&lt;br /&gt;57 44 2 65 53 50 7 95 80 56&lt;br /&gt;&lt;br /&gt;57 44 65 95&lt;br /&gt;57 44 65 80&lt;br /&gt;57 44 53 56&lt;br /&gt;57 2 50&lt;br /&gt;57 2 7&lt;br /&gt;&lt;br /&gt;Then let's start at the top of the tree and see what happens:&lt;br /&gt;&lt;br /&gt;57: 44 2 -&amp;gt; 2: 44 57&lt;br /&gt;&lt;br /&gt;57: 50 7 -&amp;gt; 7: 50 57&lt;br /&gt;&lt;br /&gt;2: 44 7&lt;br /&gt;&lt;br /&gt;and that's all we have to do because everything else is a leaf, or nothing has changed.  So our new heap:&lt;br /&gt;&lt;br /&gt;2 44 7 65 53 50 57 95 80 56&lt;br /&gt;&lt;br /&gt;2 44 65 95&lt;br /&gt;2 44 65 80&lt;br /&gt;2 44 53 56&lt;br /&gt;2 7 50&lt;br /&gt;2 7 57&lt;br /&gt;&lt;br /&gt;And lo, once again, all the paths are sorted and the lowest number in the heap is at the front.&lt;br /&gt;&lt;br /&gt;Fun.&lt;br /&gt;&lt;br /&gt;so, now, how does this apply to priority queues?  Well, rather simply: by re-sorting the heap before and after each removal, we always guarantee that we get the lowest thing out of the heap.  And since we can put in any number and ensure that it fits in the heap, we can do that too.&lt;br /&gt;&lt;br /&gt;Here's the entire thing about heaps:&lt;br /&gt;&lt;br /&gt;1. the heap operation is "swap the node index k with the smallest number in indices k, 2k+1, 2k+2.&lt;br /&gt;2. whenever you change any part of the heap, either through addition or deletion of nodes, or by swapping of nodes, run the heap operation on all trios of numbers where at least one number has changed.&lt;br /&gt;3. when adding a node, add it at the end, and do rule 2.&lt;br /&gt;4. when deleting a node, replace it with the one from the end, and do rule 2.&lt;br /&gt;&lt;br /&gt;That's it.  There's nothing more to it.&lt;br /&gt;&lt;br /&gt;There's another kind of heap, which is used for memory management, but this ain't it.  The ancient Mac error "stack collision with a heap" is an emergency with just such a structure.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:3109</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/3109.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=3109"/>
    <title>Dijkstra's Algorithm (old)</title>
    <published>2005-05-04T04:56:05Z</published>
    <updated>2005-05-04T04:56:05Z</updated>
    <content type="html">Imagine for a moment that you have highway map of the United States, and you want to find the shortest highway route from New York to Los Angeles.  How would you do it?  What's the fastest way to find this?&lt;br /&gt;&lt;br /&gt;This looks like a job for Dijkstra's Algorithm.&lt;br /&gt;&lt;br /&gt;What you actually have in that map is known to mathematicians as an edge-weighted graph:  you have a set of points (cities, junctions), and the distances between any directly connected pair of points.  What you want to do is take this graph and repeatedly find the shortest path from your start point (New York) to any point you haven't yet visited, and do this until you have visited Los Angeles.&lt;br /&gt;&lt;br /&gt;You're going to need a couple of toys for this one, so I'll describe them.&lt;br /&gt;&lt;br /&gt;1. a dictionary (aka a mapping or an associative array) - something you can look places up in quickly.  As we visit each point, we will put it in the dictionary, with some other information.  &lt;br /&gt;2. a priority queue - a container that sorts things as you put them in, and when you take something out, you always get the smallest thing that you've put in so far and haven't taken out. &lt;br /&gt;&lt;br /&gt;Both of these structures can be found for just about any language you want to use.  Anyway.  Our dictionary will store the name of a point as the "key" - the thing we've made it look up easily - and a "predecessor" (a point name) and a "distance" (a number) as the "value".  Our priority queue will store all three of these things as well, but will sort on the distance.  NOTE: you can also store the dictionary information in the points themselves... especially if you have a much simpler way (references, pointers, indices into an array) to get to any particular point.&lt;br /&gt;&lt;br /&gt;Now, for the algorithm itself.&lt;br /&gt;&lt;br /&gt;1. The dictionary starts empty (or, if you're storing with the points themselves, start each one's distance at -1, and its predecessor set to null or another invalid value.  We'll use this invalidity to show that the point hasn't been visited.).  the priority queue starts with our starting point in it, with distance 0 and an invalid predecessor (an empty string would work in our case).&lt;br /&gt;&lt;br /&gt;2. Remove a point from the priority queue, and examine it.  If this point is already in the dictionary, throw this point out and start this step over.  Now look at the graph (or roadmap).  You'll notice that you have several possible points directly connected to it, and each one has a distance from our current point.  For each one of these that isn't already in our dictionary, put an object into the priority queue, with the same name as the point, a predecessor with the name of the point we just took out of the queue, and a distance that's the sum of the distance in the object we took out of the queue plus the distance along the road (graph edge) between these two points.&lt;br /&gt;&lt;br /&gt;3. go back to step 2, until the priority queue is empty or you have put your destination point into the dictionary.&lt;br /&gt;&lt;br /&gt;4. look up your destination point in the dictionary, and add it to an empty list.  This will be your current point.&lt;br /&gt;&lt;br /&gt;5. change the current point to the one listed in the predecessor field of the current point.  Add this new point to that list.&lt;br /&gt;&lt;br /&gt;6. repeat step 5 until you reach a point with an invalid predecessor field... this is your starting point.&lt;br /&gt;&lt;br /&gt;7. reverse the list, and you have a complete set of directions from start to finish.&lt;br /&gt;&lt;br /&gt;Now, this looks like a hell of a lot of work to get one set of directions, and sure, it is.  But get this:  Once you've done steps 1-3 once for a given origin point, &lt;b&gt;you never have to do them again for that origin&lt;/b&gt;.  You can start at step 4 for every single destination point from that origin once these steps are done.&lt;br /&gt;&lt;br /&gt;Dijkstra's Algorithm runs in O(n&lt;sup&gt;2&lt;/sup&gt;) time.  This can be proven to be the fastest graph traversal algorithm... but I'm not going to do it right now.  You can look it up.&lt;br /&gt;&lt;br /&gt;There are other pathfinding algorithms that work better when you can learn more about the layout... but if I go any deeper into this I'll be into Artificial Intelligence, and I don't know jack about it.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:3026</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/3026.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=3026"/>
    <title>Floating Point Precision (old)</title>
    <published>2005-05-04T04:54:31Z</published>
    <updated>2008-06-14T21:13:39Z</updated>
    <content type="html">Imagine, for a moment, that you have a number storage format, that allows you to store five consecutive digits that appear anywhere in a number.  These digits can be ANYTHING... but the rest of the digits in any number must end up being zero.  So you can store 12345, or 1234500, or 0.00000012345, or 1.0005, but not 123456, or 1.02345 , because in each case we have more than five consecutive digits to store.&lt;br /&gt;&lt;br /&gt;So what happens when we try to do 12345 + 0.1 ?  Well, we probably get 12345.  And that's it.&lt;br /&gt;&lt;br /&gt;The scary thing about this is that it's not associative:  (a + b) + c does not necessarily come up with the same result as a + (b + c):&lt;br /&gt;&lt;br /&gt;(1000.4 + 0.2) + 10000 = 1000.6 + 10000 = 11001&lt;br /&gt;1000.4 + (0.2 + 10000) = 1000.4 + 10000 = 11000&lt;br /&gt;&lt;br /&gt;In a computer, numbers are not stored in decimal, but the same principle applies: you can only store a number that you only need 52 bits to store, so that the smallest number above 1 that you can store is 1.0000000000000002220446049250313080847263336181640625, and not one iota less.  That excess is known as &lt;i&gt;epsilon&lt;/i&gt;, and you'll see it a lot.  If you go through my previous posts, any time a difference number repeats, it's a power of 2 times this number.  The reason the algorithms I use get this close but no further is because I have intentionally limited myself to using the standard internal format of the machine, and have decided not to use more accurate but more difficult methods.  Yes, I'm lazy.&lt;br /&gt;&lt;br /&gt;There.  I haven't done anything too frightening in this one, so NO CUT FOR YOU!  COME BACK, ONE POST!  It'll probably be about graphs.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:2679</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/2679.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=2679"/>
    <title>Exponential Functions (old)</title>
    <published>2005-05-04T04:51:23Z</published>
    <updated>2005-05-04T04:51:23Z</updated>
    <content type="html">This is the last, I think, of the elementary functions that I'm going to cover.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;The function a&lt;sup&gt;b&lt;/sup&gt; can look astonishingly easy (if b is an integer) or astonishingly hard (if it is not).  In both situations, however, it is rather simple to get a result.  Note: A must be positive, or this won't work.  Like, at all.&lt;br /&gt;&lt;br /&gt;First, we need to note that we can find e&lt;sup&gt;x&lt;/sup&gt; through a Taylor series, and an especially simple one:  e&lt;sup&gt;x&lt;/sup&gt; = 1 + x/1 + x&lt;sup&gt;2&lt;/sup&gt;/2 + x&lt;sup&gt;3&lt;/sup&gt;/6 + .... + x&lt;sup&gt;k&lt;/sup&gt;/k! .&lt;br /&gt;&lt;br /&gt;Now:  a&lt;sup&gt;b&lt;/sup&gt; = e&lt;sup&gt;b ln(a)&lt;/sup&gt; .  We already know how to get logarithms, so this is pretty simple.  Note that you're going to need a LOT of precision in calculating ln(a) to get it to work properly.&lt;br /&gt;&lt;br /&gt;Here's our whole process.&lt;br /&gt;&lt;br /&gt;1. get the natural logarithm of a, and multiply it by b.  Call this x.&lt;br /&gt;2. set n and k to 1, and result to 0.&lt;br /&gt;3. add n to result.&lt;br /&gt;4. n = n * x / k.&lt;br /&gt;5. increment k.&lt;br /&gt;6. go to step 3.&lt;br /&gt;&lt;br /&gt;And here's a table.&lt;br /&gt;&lt;table style="text-align: right"&gt;
  &lt;tr&gt;&lt;td&gt;k&lt;/td&gt;&lt;td&gt;n&lt;/td&gt;&lt;td&gt;result&lt;/td&gt;&lt;td&gt;|result - right answer|&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;2.07944154167984&lt;/td&gt;&lt;td&gt;3.07944154167984&lt;/td&gt;&lt;td&gt;4.92055845832016&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;2.16203856263191&lt;/td&gt;&lt;td&gt;5.24148010431174&lt;/td&gt;&lt;td&gt;2.75851989568826&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;1.49861093395018&lt;/td&gt;&lt;td&gt;6.74009103826192&lt;/td&gt;&lt;td&gt;1.25990896173808&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;0.779068457717906&lt;/td&gt;&lt;td&gt;7.51915949597983&lt;/td&gt;&lt;td&gt;0.48084050402017&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;0.324005462958211&lt;/td&gt;&lt;td&gt;7.84316495893804&lt;/td&gt;&lt;td&gt;0.156835041061959&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;0.112291736567752&lt;/td&gt;&lt;td&gt;7.95545669550579&lt;/td&gt;&lt;td&gt;0.0445433044942076&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;0.0333577288294788&lt;/td&gt;&lt;td&gt;7.98881442433527&lt;/td&gt;&lt;td&gt;0.0111855756647286&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;0.00867068088301367&lt;/td&gt;&lt;td&gt;7.99748510521828&lt;/td&gt;&lt;td&gt;0.00251489478171507&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;0.00200335266919865&lt;/td&gt;&lt;td&gt;7.99948845788748&lt;/td&gt;&lt;td&gt;0.000511542112516139&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;0.000416585476296685&lt;/td&gt;&lt;td&gt;7.99990504336378&lt;/td&gt;&lt;td&gt;0.000094956636219834&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;7.87513768247098E-05&lt;/td&gt;&lt;td&gt;7.99998379474061&lt;/td&gt;&lt;td&gt;1.62052593948303E-05&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;1.36465737028153E-05&lt;/td&gt;&lt;td&gt;7.99999744131431&lt;/td&gt;&lt;td&gt;2.55868569176698E-06&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;2.1828655584023E-06&lt;/td&gt;&lt;td&gt;7.99999962417987&lt;/td&gt;&lt;td&gt;3.75820133236004E-07&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;3.24224380145992E-07&lt;/td&gt;&lt;td&gt;7.99999994840425&lt;/td&gt;&lt;td&gt;5.15957534474865E-08&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;4.4947042993398E-08&lt;/td&gt;&lt;td&gt;7.99999999335129&lt;/td&gt;&lt;td&gt;6.64871002697964E-09&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;5.84154677350884E-09&lt;/td&gt;&lt;td&gt;7.99999999919284&lt;/td&gt;&lt;td&gt;8.07163225147178E-10&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;7.14538531088241E-10&lt;/td&gt;&lt;td&gt;7.99999999990738&lt;/td&gt;&lt;td&gt;9.26245746768473E-11&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;8.25467280375432E-11&lt;/td&gt;&lt;td&gt;7.99999999998992&lt;/td&gt;&lt;td&gt;1.00781605283373E-11&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;9.0342681795271E-12&lt;/td&gt;&lt;td&gt;7.99999999999896&lt;/td&gt;&lt;td&gt;1.04360964314765E-12&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;9.39311627559246E-13&lt;/td&gt;&lt;td&gt;7.9999999999999&lt;/td&gt;&lt;td&gt;1.03916875104915E-13&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;9.30116009014092E-14&lt;/td&gt;&lt;td&gt;7.99999999999999&lt;/td&gt;&lt;td&gt;1.06581410364015E-14&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;8.79146303511527E-15&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;1.77635683940025E-15&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;7.94840584667887E-16&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;8.88178419700125E-16&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;6.88676887821455E-17&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;8.88178419700125E-16&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Next Time: probably floating point precision.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:2547</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/2547.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=2547"/>
    <title>Trigonometry (old)</title>
    <published>2005-05-04T04:48:04Z</published>
    <updated>2005-05-04T04:48:04Z</updated>
    <content type="html">So I said to myself, self, I you've written short bits on square roots, and on logarithms, why not do something on other common functions?&lt;br /&gt;&lt;br /&gt;Self, said I, that's a great idea.&lt;br /&gt;&lt;br /&gt;The trigonometric functions - sine, cosine, tangent, cotangent, secant, and cosecant - are extremely common in many branches of math and science, including graphics processing.  Fortunately they're easy to deal with.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;Tangent, Cotangent, Secant, and Cosecant are generally not calculated directly, because they can be derived easily:&lt;br /&gt;&lt;br /&gt;tan(x) = sin(x)/cos(x)&lt;br /&gt;cot(x) = cos(x)/sin(x)&lt;br /&gt;sec(x) = 1/cos(x)&lt;br /&gt;csc(x) = 1/sin(x)&lt;br /&gt;&lt;br /&gt;So all we're left with is sine and cosine.  Technically we can derive one from the other, but we're not going to do that.  Why not?  Because they're both exceedingly beautiful.&lt;br /&gt;&lt;br /&gt;Each is generally modeled by a Taylor series, a polynomial that is defined in such a way that it gets closer and closer to the right answer the more terms you figure.  Here are the Taylor series for sine and cosine:&lt;br /&gt;&lt;br /&gt;sin(x) = SUM((-1)&lt;sup&gt;n&lt;/sup&gt;x&lt;sup&gt;2n+1&lt;/sup&gt;/(2n+1)!,n=0,inf)&lt;br /&gt;cos(x) = SUM((-1)&lt;sup&gt;n&lt;/sup&gt;x&lt;sup&gt;2n&lt;/sup&gt;/(2n)!,n=0,inf)&lt;br /&gt;&lt;br /&gt;That's all well and good, but it doesn't get us immediately to a quick way to do it.  So here's some observations:&lt;br /&gt;&lt;br /&gt;1. in both series, each successive term is reachable from the previous by multiplying by x&lt;sup&gt;2&lt;/sup&gt; and then dividing by 2n and one of 2n-1 or 2n+1, depending on which one you're doing.&lt;br /&gt;2. in both series, we have the sign flipping back and forth, and they both start with the sign positive.&lt;br /&gt;3. we can determine the next term given 2n, the sign, and the current term.  With a little bit of trickery, we can even do the next term for both of them &lt;b&gt;in the same way&lt;/b&gt;, after a few little bits of startup.&lt;br /&gt;&lt;br /&gt;So let's do that.&lt;br /&gt;&lt;br /&gt;1s. (sine)  current = x; k = 1; s = 1&lt;br /&gt;1c. (cosine) current = 1; k = 0; s = 1&lt;br /&gt;2. result = result + current * s&lt;br /&gt;3. current = current * x * x / ((k + 1) * (k + 2))&lt;br /&gt;4. k = k + 2&lt;br /&gt;5. s = -s&lt;br /&gt;6. go to step 2, until you think you've got it close enough.  There's a trick to figuring out how close you need to be for a certain thing, but it's more involved than I like.&lt;br /&gt;&lt;br /&gt;So, here's a sine and a cosine, done the Taylor Series way.  Also listed is the difference between the current result and the actual result.&lt;br /&gt;&lt;br /&gt;SIN(pi/3)&lt;br /&gt;&lt;table&gt;
&lt;tr&gt;&lt;td&gt;current&lt;/td&gt;&lt;td&gt;k&lt;/td&gt;&lt;td&gt;s&lt;/td&gt;&lt;td&gt;result&lt;/td&gt;&lt;td&gt;difference&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.047 197 551                 &lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;1.047 197 551&lt;/td&gt;&lt;td&gt;0.181 172 147&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.191 396 769                 &lt;/td&gt;&lt;td&gt; 3&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.855 800 781&lt;/td&gt;&lt;td&gt;0.010 224 622&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.010 494 502                 &lt;/td&gt;&lt;td&gt; 5&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 295 283&lt;/td&gt;&lt;td&gt;0.000 269 880&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.000 274 012                 &lt;/td&gt;&lt;td&gt; 7&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 021 271&lt;/td&gt;&lt;td&gt;4.132 128 066*10&lt;sup&gt; -6&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4.173 443 408*10&lt;sup&gt; -6&lt;/sup&gt;&lt;/td&gt;&lt;td&gt; 9&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 025 445&lt;/td&gt;&lt;td&gt;4.131 534 248*10&lt;sup&gt; -8&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4.160 629 841*10&lt;sup&gt; -8&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 025 403&lt;/td&gt;&lt;td&gt;2.909 559 260*10&lt;sup&gt;-10&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2.924 769 985*10&lt;sup&gt;-10&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 025 403&lt;/td&gt;&lt;td&gt;1.521 116 566*10&lt;sup&gt;-12&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.527 318 662*10&lt;sup&gt;-12&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 025 403&lt;/td&gt;&lt;td&gt;6.217 248 937*10&lt;sup&gt;-15&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;6.157 692 399*10&lt;sup&gt;-15&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 025 403&lt;/td&gt;&lt;td&gt;1.110 223 024*10&lt;sup&gt;-16&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.974 463 547*10&lt;sup&gt;-17&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 025 403&lt;/td&gt;&lt;td&gt;1.110 223 024*10&lt;sup&gt;-16&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;5.155 337 069*10&lt;sup&gt;-20&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.866 025 403&lt;/td&gt;&lt;td&gt;1.110 223 024*10&lt;sup&gt;-16&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;COS(pi/3)&lt;br /&gt;&lt;table&gt;
&lt;tr&gt;&lt;td&gt;current&lt;/td&gt;&lt;td&gt;k&lt;/td&gt;&lt;td&gt;s&lt;/td&gt;&lt;td&gt;result&lt;/td&gt;&lt;td&gt;difference&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.000 000 000                 &lt;/td&gt;&lt;td&gt; 0&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;1.000 000 000&lt;/td&gt;&lt;td&gt;0.500 000 000&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.548 311 355                 &lt;/td&gt;&lt;td&gt; 2&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.451 688 644&lt;/td&gt;&lt;td&gt;0.048 311 355&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.050 107 557                 &lt;/td&gt;&lt;td&gt; 4&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.501 796 201&lt;/td&gt;&lt;td&gt;0.001 796 201&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.001 831 636                 &lt;/td&gt;&lt;td&gt; 6&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.499 964 565&lt;/td&gt;&lt;td&gt;3.543 467 108*10&lt;sup&gt;-5&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;3.586 810 400*10&lt;sup&gt; -5&lt;/sup&gt;&lt;/td&gt;&lt;td&gt; 8&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.500 000 433&lt;/td&gt;&lt;td&gt;4.334 329 148*10&lt;sup&gt;-7&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4.370 419 717*10&lt;sup&gt; -7&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.499 999 996&lt;/td&gt;&lt;td&gt;3.609 056 886*10&lt;sup&gt;-9&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;3.630 834 484*10&lt;sup&gt; -9&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.500 000 000&lt;/td&gt;&lt;td&gt;2.177 757 973*10&lt;sup&gt;-11&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2.187 722 833*10&lt;sup&gt;-11&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.499 999 999&lt;/td&gt;&lt;td&gt;9.964 251 646*10&lt;sup&gt;-14&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;9.996 277 270*10&lt;sup&gt;-14&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.500 000 000&lt;/td&gt;&lt;td&gt;3.330 669 073*10&lt;sup&gt;-16&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;3.582 400 223*10&lt;sup&gt;-16&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.500 000 000&lt;/td&gt;&lt;td&gt;0.000 000 000&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.033 826 696*10&lt;sup&gt;-18&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.500 000 000&lt;/td&gt;&lt;td&gt;0.000 000 000&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;As you can see, this converges very quicky.  By the time we've done ten iterations, we have exceeded the ability of the machine (actually Excel) to add the newest current value to the result, and we're devastatingly close to the correct value.&lt;br /&gt;&lt;br /&gt;I think I'll do maybe one or two more of the elementary functions (I should cover exponents because they do something cute to be more general, and then maybe some scary tricks), and then we'll move on to something different.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:2112</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/2112.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=2112"/>
    <title>Logarithms (old)</title>
    <published>2005-05-04T04:44:02Z</published>
    <updated>2006-02-12T07:36:41Z</updated>
    <content type="html">If you've ever done math beyond algebra you've probably used logarithms.  Logarithms log&lt;sub&gt;b&lt;/sub&gt;(x) are defined such that b&lt;sup&gt;log(x)&lt;/sup&gt; = x.  You probably knew that.  You probably didn't know how to calculate them.  Shockingly, it's really easy.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;This sort of thing is easiest to do when b is 10 or when b is 2; if you need a different b (say, e), you can later divide by log&lt;sub&gt;b&lt;/sub&gt;(e) or similar. &lt;br /&gt;&lt;br /&gt;Start by dividing x by b until 1 &amp;le; x &amp;lt; b.  The number of times you have to do that is the integer part of the logarithm.  If x &amp;lt; 1 already, multiply instead of dividing, and the integer part is negative.&lt;br /&gt;&lt;br /&gt;Now, we need some numbers:  size = 0.5.&lt;br /&gt;&lt;br /&gt;Square the current value of x.  If it is now &amp;gt; b, add size to the integer part and divide x by b.  Halve size.&lt;br /&gt;&lt;br /&gt;Do this again, until you have enough precision.&lt;br /&gt;&lt;br /&gt;Here's log&lt;sub&gt;10&lt;/sub&gt;(2).&lt;br /&gt;&lt;br /&gt;1 &amp;le; 2 &amp;lt; 10, so integer part is 0.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;
  &lt;tr style="font-style: italic"&gt;&lt;td&gt;x&lt;/td&gt;&lt;td&gt;bit&lt;/td&gt;&lt;td&gt;size&lt;/td&gt;&lt;td&gt;result&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;4.000 000&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.500 000&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.000 000&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1.600 000&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.250 000&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.250 000&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;2.560 000&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.125 000&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.250 000&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;6.553 600&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.062 500&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.250 000&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;4.294 967&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.031 250&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.281 250&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1.844 674&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.015 625&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.296 875&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;3.402 823&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.007 812&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.296 875&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1.157 920&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.003 906&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.300 781&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1.340 780&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.001 953&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.300 781&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1.797 693&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.000 976&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.300 781&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;3.231 700&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.000 488&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.300 781&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1.044 388&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.000 244&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.301 025&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1.090 748&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0.000 122&lt;/td&gt;&lt;td style="font-weight: bold"&gt;0.301 025&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Technically you can do this using a higher power (instead of squaring), but then you need to divide multiple times in each step.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:1978</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/1978.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=1978"/>
    <title>Squaring and Taking Square Roots (old)</title>
    <published>2005-05-04T04:43:02Z</published>
    <updated>2005-05-04T04:43:02Z</updated>
    <content type="html">Last night I dreamed of algorithms.  That sadness out of the way, let me show you a way to square a number, and then reverse the process to get the square root.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;Before this will make any sense to you:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;
  &lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;(x + k)&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;x&lt;sup&gt;2&lt;/sup&gt; + 2xk + k&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;x&lt;sup&gt;2&lt;/sup&gt; + (2x + k)k&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;x&lt;sup&gt;2&lt;/sup&gt; + ((x + k) + x)k&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;What this means is essentially this:  if I know the square of one number, and I need the square of another number, I can add the first number and the second number, multiply it by the difference between the two numbers, and add that to the square of the original number.  For example:&lt;br /&gt;&lt;br /&gt;30&lt;sup&gt;2&lt;/sup&gt; = 900&lt;br /&gt;32&lt;sup&gt;2&lt;/sup&gt; = 900 + (30 + 32) * 2 = 900 + 124 = 1024&lt;br /&gt;&lt;br /&gt;Now, we know that 10&lt;sup&gt;2&lt;/sup&gt; = 100, and that 100&lt;sup&gt;2&lt;/sup&gt; = 10,000.  Each digit we go away from the decimal point in the original brings us 2 digits away in the square.  So what we're going to do is:&lt;br /&gt;&lt;br /&gt;0. set up a table so that one digit in the top row is equivalent to two digits in any other row.&lt;br /&gt;1. start at the leftmost digit.  Square it, and put the result directly under that digit.&lt;br /&gt;2. advance to the right one digit.  If there are no more digits, go to step 6.&lt;br /&gt;3. take the digits before our current digit, treat them as a number, double it, and append the current digit to the end of that.&lt;br /&gt;4. multiply that number by the current digit, and put the result under the current digit, using cells to the left if we have to.&lt;br /&gt;5. go to step 2.&lt;br /&gt;6. add all rows except for the topmost row.  This is your result.&lt;br /&gt;&lt;br /&gt;&lt;table style="text-align: right"&gt;
  &lt;tr style="text-align: center; font-style: italic"&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;       8&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt; 9&lt;/td&gt;&lt;td&gt;96&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;     166&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;996&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;89&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;    1727&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;12089&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 8&lt;/td&gt;&lt;td&gt;67&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;   17345&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;86725&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;52&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;05&lt;/td&gt;&lt;td&gt;09&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  173503&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;520509&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 0&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 1735060&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;56&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;54&lt;/td&gt;&lt;td&gt;81&lt;/td&gt;&lt;td&gt;17350609&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;156155481&lt;/td&gt;&lt;/tr&gt;
  &lt;tr style="font-weight: bold"&gt;&lt;td&gt;75&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;09&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;86&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;54&lt;/td&gt;&lt;td&gt;81&lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Now you're probably looking at this and going, "Man.  That's a really crappy way to do this."  And you'd be right.  There's much easier ways to square a number; the usual method is generally much more efficient because you're always multiplying by the same number.  But the thing is that the fact that we can square a number this way means that we can reverse the process to get the square root of a number.&lt;br /&gt;&lt;br /&gt;here's how we take the square root:&lt;br /&gt;&lt;br /&gt;1. chop up the number into 2-digit chunks, starting at the decimal point:  6 35 . 50 is okay, 63 5.5 is not.&lt;br /&gt;2. bring down the leftmost unused pair of digits and place it to the right of any remainder (the remainder comes from step 4).  If the remainder is 0 and there are no more non-zero number pairs, the algorithm terminates.&lt;br /&gt;3. take the result so far and find the largest digit k such that (20*result + k) * k is less than the number on the remainder line.&lt;br /&gt;4. subtract (20 * result + k) * k from the remainder line to make a new remainder line.  Append k to the end of the result.&lt;br /&gt;&lt;br /&gt;&lt;table style="text-align: right"&gt;
  &lt;tr style="text-align: center; font-weight: bold"&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt;
  &lt;tr style="font-style: italic"&gt;&lt;td&gt;75&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;09&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;86&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;54&lt;/td&gt;&lt;td&gt;81&lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;       8&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;       64&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt; 9&lt;/td&gt;&lt;td&gt;96&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;     166&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;      996&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt;30&lt;/td&gt;&lt;td&gt;09&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;89&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;    1727&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;    12089&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 9&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;86&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt; 
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 8&lt;/td&gt;&lt;td&gt;67&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;   17345&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;    86725&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;53&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;61&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt; 
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;52&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;05&lt;/td&gt;&lt;td&gt;09&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  173503&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;   520509&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;56&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;54&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt; 
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 0&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 1735060&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;        0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;56&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;54&lt;/td&gt;&lt;td&gt;81&lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt; 
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 1&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;56&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;54&lt;/td&gt;&lt;td&gt;81&lt;/td&gt;&lt;td&gt;17350609&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;156155481&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt;  &lt;/td&gt;&lt;td&gt; 0&lt;/td&gt;&lt;td&gt;        &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt;         &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Yes, there are faster ways of getting square roots... but how many of them actually give you an exact answer when it exists?&lt;br /&gt;&lt;br /&gt;I'm mainly proud of myself because I figured out how they managed to come up with this silly algorithm.&lt;br /&gt;&lt;br /&gt;Also, I have Tommy Tutone stuck in my head.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:1584</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/1584.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=1584"/>
    <title>Gaussian Elimination (old)</title>
    <published>2005-05-04T04:41:09Z</published>
    <updated>2005-05-04T04:41:09Z</updated>
    <content type="html">For all that I talk about code, I sure don't write it very fast.&lt;br /&gt;&lt;br /&gt;Gaussian Elimination is a very simple process that is used to solve systems of equations in the form of an augmented matrix (a square matrix with a vector attached to the side).  Basically you use row operations (swap two rows, multiply one row by a number, and add a multiple of one row to a second row) on the matrix to make it so all the non-zero values are on the diagonal.  Here's some code.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;pre&gt;template &amp;lt;size_t size&amp;gt;
MathVector&amp;lt;size&amp;gt; gaussianElimination(SquareMatrix&amp;lt;size&amp;gt; m, MathVector&amp;lt;size&amp;gt; v) {
  size_t j,k;
  double mult;
  for (k = 0; k &amp;lt; size; k++) {
    j = k;
    while(m.index(j,k) == 0) { // find a row we haven't used that has a nonzero value in the kth column
      j++;
      if (j == size) throw NonDiagonalizableMatrix; // no such row exists; we're screwed
    }
    m.rowSwap(j,k); // make said row the kth row.
    swap(v[j],v[k]); // do the same to the vector
    for (j = 0; j &amp;lt; size; j++) { // manipulate each row using the current primary row
      if (j != k) { // don't manipulate the primary row.
        mult = -m.index(j,k);
        m.rowMult(j, m.index(k,k); // multiply the secondary row by the kth value of the kth row
        v[j] *= m.index(k,k);
        m.rowAdd(j, k, mult); // add enough of the primary row to the secondary row to zero out the kth value
        v[j] += v[k] * mult;
      }
    }
  }
  for (k = 0; k &amp;lt; size; k++)
    v[k] /= m.index(k, k); // set all the values in the matrix to 1, but only bother with it on the vector side.
  return v;
}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Using Gaussian Elimination is fine, if you're only going to be solving the system of equations once.  However, often you want to go one better than that, and solve the equations several times; in which case you're probably better off using Gauss-Jordan Elimination (basically, the same process, except the vector is replaced by a specific matrix) to get the inverse of the matrix, which will allow you to find the inverse of the matrix, and solve the system of equations very quickly for a lot of different outputs.&lt;br /&gt;&lt;br /&gt;Vorn</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:cs_lectures:1354</id>
    <author>
      <name>Vorn the Unspeakable</name>
    </author>
    <lj:poster user="unspeakablevorn"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/cs_lectures/1354.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/cs_lectures/data/atom/?itemid=1354"/>
    <title>Boolean logic and Generative Grammars (old)</title>
    <published>2005-05-04T04:39:56Z</published>
    <updated>2005-05-04T04:39:56Z</updated>
    <content type="html">&lt;a name="cutid1"&gt;&lt;/a&gt;There is an operation known as NAND, which takes two bits (or boolean values, if you want to think of them that way) and turns them into one, in such a way that the result is 1 if and only if at least one of the inputs is 0.  That is to say:&lt;br /&gt;&lt;table border="1"&gt;
  &lt;tr&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;A NAND B&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;NAND is a very powerful tool - with it and it alone you can make any possible operation on bits that you want.&lt;br /&gt;&lt;br /&gt;With that in mind, let's see if we can figure out how to make any given operation on two bits.  Further, let us see if we can make this in such a way that we have the fewest levels of NANDs - that is to say, if we can make any number of NAND operations simultaneously, but can't use the result of an operation until you've finished it.  How would we go about it?&lt;br /&gt;&lt;br /&gt;One way is using a generative grammar.  A generative grammar is a set of rules which describe how to make well-formed statements from simpler well-formed statements, and a set of axioms which describe the simplest possible well-formed statements.&lt;br /&gt;&lt;br /&gt;Here's our generative grammar for solving the NAND problem:&lt;br /&gt;&lt;br /&gt;RULES&lt;br /&gt;&lt;table border="1"&gt;
  &lt;tr&gt;&lt;td&gt;rule&lt;/td&gt;&lt;td&gt;value&lt;/td&gt;&lt;td&gt;price&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;statement := (statement1 statement2)&lt;/td&gt;&lt;td&gt;~statement1 | ~statement2&lt;/td&gt;&lt;td&gt;maxprice(statement1,statement2) + 1&lt;/td&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;AXIOMS&lt;br /&gt;&lt;table border="1"&gt;
  &lt;tr&gt;&lt;td&gt;statement&lt;/td&gt;&lt;td&gt;value&lt;/td&gt;&lt;td&gt;price&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;0x3&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
  &lt;tr&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;0x5&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;The axioms are defined such that each bit represents a different pair of inputs to the NAND function.&lt;br /&gt;&lt;br /&gt;Given these rules and axioms, we can create an algorithm that creates all possible statements.  Note that NAND is commutative, so we don't have to worry about things where i &amp;lt; j:&lt;br /&gt;&lt;pre&gt;while i &amp;lt; len(statements):
  while j &amp;lt;= i:
    statements.push(createStatement(statements[i],statements[j]))
    j++
  i++&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We will watch carefully our list of statements while we run this.&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;
  &lt;tr&gt;&lt;td&gt;#&lt;/td&gt;&lt;td&gt;i&lt;/td&gt;&lt;td&gt;j&lt;/td&gt;&lt;td&gt;statement&lt;/td&gt;&lt;td&gt;value&lt;/td&gt;&lt;td&gt;price&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;(AA)&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;(BA)&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;(BB)&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;((AA)A)&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;((AA)B)&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;((AA)(AA))&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;((BA)A)&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;((BA)B)&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;((BA)(AA))&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;((BA)(BA))&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;((BB)A)&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;((BB)B)&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;((BB)(AA))&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;((BB)(BA))&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;((BB)(BB))&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;As you can see this can get pretty ugly pretty fast.  To list all the price 3 statements we need to go to #154, and to get all the price 4 statements we need to go to #12091.  Fortunately, we don't have to go beyond price 3, because once we've finished that we have all possible values.&lt;br /&gt;&lt;br /&gt;Now that we have all the possible values, let's look at the ways we can get them.  The following table lists all the ways we can get a particular value for its minimum price.&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;
  &lt;tr&gt;&lt;td&gt;#&lt;/td&gt;&lt;td&gt;i&lt;/td&gt;&lt;td&gt;j&lt;/td&gt;&lt;td&gt;statement&lt;/td&gt;&lt;td&gt;value&lt;/td&gt;&lt;td&gt;price&lt;/td&gt;&lt;td&gt;gates&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;(((AA)A)((AA)A))&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;98&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;(((BB)B)((AA)A))&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;106&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;(((BB)B)((BB)B))&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;((BA)(BA))&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;43&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;(((BA)A)((AA)A))&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;46&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;(((BA)A)((BA)A))&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;85&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;(((BB)A)((AA)A))&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;88&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;(((BB)A)((BA)A))&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;92&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;(((BB)A)((BB)A))&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;101&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;(((BB)B)((BA)A))&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;105&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;(((BB)B)((BB)A))&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;(((AA)B)((AA)A))&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;29&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;(((AA)B)((AA)B))&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;52&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;(((BA)B)((AA)A))&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;53&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;(((BA)B)((AA)B))&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;56&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;(((BA)B)((BA)B))&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;99&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;(((BB)B)((AA)B))&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;102&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;(((BB)B)((BA)B))&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;44&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;(((BA)A)((AA)B))&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;55&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;(((BA)B)((BA)A))&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;86&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;(((BB)A)((AA)B))&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;89&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;(((BB)A)((BA)B))&lt;/td&gt;&