{"id":5519,"date":"2018-09-09T13:00:17","date_gmt":"2018-09-09T13:00:17","guid":{"rendered":"http:\/\/writeasync.net\/?p=5519"},"modified":"2018-09-09T02:10:22","modified_gmt":"2018-09-09T02:10:22","slug":"exact-square-roots-continued","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=5519","title":{"rendered":"Exact square roots (continued)"},"content":{"rendered":"<p>Last week, I introduced a <a href=\"http:\/\/writeasync.net\/?p=5516\">data structure kata involving exact square roots<\/a>. At the time of that writing, I had implemented a <code>RootTerm<\/code> struct which could represent real and imaginary square roots. Today we&#8217;ll pick up where we left off by implementing addition and multiplication operations.<\/p>\n<p>Multiplication turns out to be the easier operation since (barring overflow) the product of two values of the form <code>C*sqrt(X)<\/code> will always be of that same form. In other words, any <code>RootTerm<\/code> times any other <code>RootTerm<\/code> will still produce a <code>RootTerm<\/code>.<\/p>\n<p>To get started, I added a failing test for products involving square roots of perfect squares (i.e. integers). Ultimately, this na\u00efve implementation emerged:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic RootTerm Multiply(RootTerm other) =&gt; new RootTerm(this.c * other.c, this.x * other.x);\r\n<\/pre>\n<p>Obviously, this doesn&#8217;t work for most cases, so I added another set of failing examples whose products become integers after simplification (e.g. <code>sqrt(3)*sqrt(27) = sqrt(81) = 9<\/code>). To make these cases work, I changed the code thusly:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic RootTerm Multiply(RootTerm other)\r\n{\r\n    RootTerm r = Sqrt(this.x * other.x);\r\n    return new RootTerm(this.c * other.c * r.c, r.x);\r\n}\r\n<\/pre>\n<p>We&#8217;re getting closer, but imaginary numbers still don&#8217;t work (e.g. <code>2i * 3i = -6<\/code>. Adding a test for this and changing the code accordingly results in this (surprisingly?) complete implementation:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic RootTerm Multiply(RootTerm other)\r\n{\r\n    int m = ((this.x &lt; 0) &amp;&amp; (other.x &lt; 0)) ? -1 : 1;\r\n    RootTerm r = Sqrt(this.x * other.x);\r\n    return new RootTerm(m * this.c * other.c * r.c, r.x);\r\n}\r\n<\/pre>\n<p>From here it was just about adding more and more &#8220;proofs by example&#8221; (unit tests). The only problem I encountered was in the formatting of the output in the <code>ToString()<\/code> method. It turns out I hadn&#8217;t needed to handle the case of a leading -1 up to that point, so I corrected the code to produce <code>-sqrt(6)<\/code> instead of the rather unsightly <code>-1*sqrt(6)<\/code>.<\/p>\n<p>For completeness, I implemented the multiply operator. It was quite literally <a href=\"https:\/\/www.madcorgi.com\/node\/8\">one line of code<\/a>:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static RootTerm operator *(RootTerm a, RootTerm b) =&gt; a.Multiply(b);\r\n<\/pre>\n<p>Now, on to addition. The full implementation would require a new data structure, but I started with a case that could be represented by a plain <code>RootTerm<\/code> &#8212; simple integers:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic RootTerm Add(RootTerm other)\r\n{\r\n    if (this.c == 0)\r\n    {\r\n        return other;\r\n    }\r\n\r\n    return new RootTerm(this.c + other.c, this.x);\r\n}\r\n<\/pre>\n<p>No sweat. A similar case with integral imaginary numbers (e.g. <code>2*i + 3*i = 5*i<\/code>) doesn&#8217;t even need any code changes. The first counterexample I decided to approach was the combination of the two previous sets &#8212; integers plus whole quantities of <code>i<\/code>, e.g. <code>2+i<\/code>. To prepare, I introduced the <code>RootSum<\/code> struct, which in essence looked like this:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic struct RootSum\r\n{\r\n    private readonly RootTerm a;\r\n    private readonly RootTerm b;\r\n\r\n    public RootSum(RootTerm a, RootTerm b)\r\n    {\r\n        this.a = a;\r\n        this.b = b;\r\n    }\r\n}\r\n<\/pre>\n<p>This was sufficient since the sum of two <code>RootTerm<\/code> values would, at worst, need to be represented by two distinct and irreducible <code>RootTerm<\/code>s. From this point on, I began to implement the addition logic, augmenting the code with various special cases to handle like terms (e.g. <code>sqrt(3)+3*sqrt(3)=4*sqrt(3)<\/code>) and to render the output in a reasonable manner.<\/p>\n<p>The final <code>Add<\/code> logic found its home in the <code>RootSum<\/code> struct directly (this seemed to make the most sense, responsibility-wise):<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static RootSum Add(RootTerm x, RootTerm y)\r\n{\r\n    if (x.IsZero)\r\n    {\r\n        return new RootSum(y, RootTerm.Zero);\r\n    }\r\n\r\n    if (y.IsZero)\r\n    {\r\n        return new RootSum(x, RootTerm.Zero);\r\n    }\r\n\r\n    if (x.X == y.X)\r\n    {\r\n        return new RootSum((x.C + y.C) * RootTerm.Sqrt(x.X), RootTerm.Zero);\r\n    }\r\n\r\n    if (x.IsReal &amp;&amp; y.IsReal)\r\n    {\r\n        if (x.X &lt; y.X)\r\n        {\r\n            return new RootSum(x, y);\r\n        }\r\n\r\n        return new RootSum(y, x);\r\n    }\r\n\r\n    if (x.IsReal)\r\n    {\r\n        return new RootSum(x, y);\r\n    }\r\n\r\n    if (y.IsReal)\r\n    {\r\n        return new RootSum(y, x);\r\n    }\r\n\r\n    if (x.X &gt; y.X)\r\n    {\r\n        return new RootSum(x, y);\r\n    }\r\n\r\n    return new RootSum(y, x);\r\n}\r\n<\/pre>\n<p>The only reason for all the different conditions is to make sure that the sum output ends up in &#8220;nice&#8221; order, specifically integers followed by square roots in ascending order with imaginary numbers last.<\/p>\n<p>One notable detour I took during this exercise was a &#8220;de-encapsulation&#8221; step to make the main <code>RootTerm<\/code> constructor public. The corresponding code was originally this part of the Add method, right when I first moved it to <code>RootSum<\/code>:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nif (x.X == y.X)\r\n{\r\n    return new RootSum(new RootTerm(x.C + y.C, x.X), RootTerm.Zero);\r\n}\r\n<\/pre>\n<p>I cringed a bit, feeling like I was spurning <a href=\"https:\/\/effectivesoftwaredesign.com\/2012\/11\/25\/on-information-hiding-and-encapsulation\/\">David Parnas himself<\/a>. But it seemed necessary at the time, <code>RootSum<\/code> not being privy to <code>RootTerm<\/code>&#8216;s private members (alas, <a href=\"https:\/\/stackoverflow.com\/questions\/203616\/why-does-c-sharp-not-provide-the-c-style-friend-keyword\">there are no friends in C#<\/a>).<\/p>\n<p>Ultimately, Parnas was avenged when I discovered a compromise to keep more of <code>RootTerm<\/code> private:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    if (x.X == y.X)\r\n    {\r\n        return new RootSum((x.C + y.C) * RootTerm.Sqrt(x.X), RootTerm.Zero);\r\n    }\r\n<\/pre>\n<p>To make this possible, I simply had to add a <code>Multiply<\/code> method\/operator which permitted products of plain old <code>Int32<\/code> and <code>RootTerm<\/code> values. This does have a minor performance implication (forcing the re-simplification of an already reduced radical) but I was more interested in exploring and solving the encapsulation problem. It just goes to show, you can always uncover something interesting while doing seemingly rote code exercises.<\/p>\n<p>If you want to follow my coding journey step-by-step, you can view the full commit history here: <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commits\/master\/projects\/RootSample\">RootSample on GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last week, I introduced a data structure kata involving exact square roots. At the time of that writing, I had implemented a RootTerm struct which could represent real and imaginary square roots. Today we&#8217;ll pick up where we left off&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[91,103,41],"tags":[],"class_list":["post-5519","post","type-post","status-publish","format-standard","hentry","category-design","category-math","category-tdd"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5519","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5519"}],"version-history":[{"count":1,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5519\/revisions"}],"predecessor-version":[{"id":5520,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5519\/revisions\/5520"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5519"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5519"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5519"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}