{"id":11220,"date":"2025-07-18T01:03:00","date_gmt":"2025-07-18T05:03:00","guid":{"rendered":"https:\/\/www.both.org\/?p=11220"},"modified":"2025-07-16T12:41:42","modified_gmt":"2025-07-16T16:41:42","slug":"a-small-algol-68-project-part-3","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=11220","title":{"rendered":"A Small Algol 68 Project, Part 3"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"11220\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p><br> <em>In memory of J. Kevin Douglas, a good friend and fellow fan of Algol 68<\/em><\/p>\n\n\n\n<p><br>In the <a href=\"https:\/\/www.both.org\/?p=11114\"><u>previous article in this series<\/u><\/a>, we diverged from the main goal of this three article mini-series &#8211; determining a best fit of a line to a data set consisting of pairs of (x,y) values. We did so in order to have some utility routines for reading delimited text files (like CSV files), and to learn a bit more about Algol 68.<\/p>\n\n\n\n<p><br>In this article, we\u2019re going to program the calculations necessary. It could be a good moment to review the first article in the series in order to remember that we are solving a matrix equation<\/p>\n\n\n\n<p><br><em>X<\/em><sup><em>T<\/em><\/sup><em> X <u>c<\/u> = X<\/em><sup><em>T<\/em><\/sup><em><u>y<\/u><\/em><\/p>\n\n\n\n<p><br>where the matrix <em>X<\/em> has <em>n<\/em> rows (<em>n<\/em> being the number of data points) and two columns (the first being the <em>x<\/em> data points, the second being all 1), and the vector <em><u>y<\/u><\/em> has <em>n<\/em> rows (containing all the <em>y<\/em> data points).<\/p>\n\n\n\n<p><br>For those of you struggling to remember how to come up with the matrix <em>X<\/em><sup><em>T<\/em><\/sup>, you can think of spinning<em> X <\/em>diagonally along the upper left &#8211; lower right dimension so that the first row is all the <em>x<\/em> values (the first column of <em>X<\/em>) and the second row is all the 1s (the second column of <em>X<\/em>).<\/p>\n\n\n\n<p><br>Then we calculate the following dot products and assign them to the elements of <em>X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><\/p>\n\n\n\n<table cellpadding=\"7\" cellspacing=\"0\" style=\"width:500px;border:none\"><tbody><tr><td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td><td>(row 1 of <em>X<\/em><sup><em>T<\/em><\/sup>) <strong>dot<\/strong> (column 1 of <em>X<\/em>)<\/td><td>(row 1 of <em>X<\/em><sup><em>T<\/em><\/sup>) <strong>dot<\/strong> (column 2 of <em>X<\/em>)<\/td><td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-right:0.18cm;padding-left:0cm\"><br><\/td><\/tr><tr><td style=\"width:2px;border-bottom:1px solid #000000;border-top:non;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td><td>(row 2 of <em>X<\/em><sup><em>T<\/em><\/sup>) <strong>dot<\/strong> (column 1 of <em>X<\/em>)<\/td><td>(row 2 of <em>X<\/em><sup><em>T<\/em><\/sup>) <strong>dot<\/strong> (column 2 of <em>X<\/em>)<\/td><td style=\"width:2px;border-bottom:1px solid #000000;border-top:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p><br>We can express these dot products as sums of multiplied terms as follows<\/p>\n\n\n\n<table cellpadding=\"7\" cellspacing=\"0\" style=\"width:400px;border:none\">\n<tbody>\n<tr>\n    <td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td>\n    <td align=\"center\"><em>x<sub>1<\/sub><sup>2<\/sup> + x<sub>2<\/sub><sup>2<\/sup> + &#8230; + x<sub>n<\/sub><sup>2<\/sup><\/em><\/td>\n    <td align=\"center\"><em>x<sub>1<\/sub> + x<sub>2<\/sub> + &#8230; + x<sub>n<\/sub><\/em><\/td>\n    <td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-right:0.18cm;padding-left:0cm\"><br><\/td> \n<\/tr>\n<tr>\n    <td style=\"width:2px;border-bottom:1px solid #000000;border-top:non;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td>\n    <td align=\"center\"><em>x<sub>1<\/sub> + x<sub>2<\/sub> + &#8230; + x<sub>n<\/sub><\/em><\/td>\n    <td align=\"center\"><em>1 + 1 + &#8230; + 1<\/em><\/td>\n    <td style=\"width:2px;border-bottom:1px solid #000000;border-top:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n\n\n<p>On the right hand side, we proceed in a similar fashion:<\/p>\n\n\n\n<table cellpadding=\"7\" cellspacing=\"0\" style=\"width:200px;border:none\"><tbody><tr><td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td><td align=\"center\">(row 1 of <em>X<\/em><sup><em>T<\/em><\/sup>) <strong>dot<\/strong> <em><u>y<\/u><\/em><\/td><td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-right:0.18cm;padding-left:0cm\"><br><\/td><\/tr><tr><td style=\"width:2px;border-bottom:1px solid #000000;border-top:non;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td><td align=\"center\">(row 2 of <em>X<\/em><sup><em>T<\/em><\/sup>) <strong>dot<\/strong> <em><u>y<\/u><\/em><\/td><td style=\"width:2px;border-bottom:1px solid #000000;border-top:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>to calculate <em>X<\/em><sup><em>T<\/em><\/sup><em><u>y<\/u><\/em>:<\/p>\n\n\n\n<table cellpadding=\"7\" cellspacing=\"0\" style=\"width:250px;border:none\">\n<tbody>\n<tr>\n    <td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td>\n    <td align=\"center\"><em>x<sub>1<\/sub> \u00b7 y<sub>1<\/sub> + x<sub>2<\/sub> \u00b7 y<sub>2<\/sub> + &#8230; + x<sub>n<\/sub> \u00b7 y<sub>n<\/sub><\/em><\/td>\n    <td style=\"width:2px;border-top:1px solid #000000;border-bottom:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-right:0.18cm;padding-left:0cm\"><br><\/td> \n<\/tr>\n<tr>\n    <td style=\"width:2px;border-bottom:1px solid #000000;border-top:non;border-left:1px solid #000000;border-right:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td>\n    <td align=\"center\"><em>y<sub>1<\/sub> + y<sub>2<\/sub> + &#8230; + y<sub>n<\/sub><\/em><\/td>\n    <td style=\"width:2px;border-bottom:1px solid #000000;border-top:none;border-right:1px solid #000000;border-left:none;padding-top:0.18cm;padding-bottom:0cm;padding-left:0.18cm;padding-right:0cm\"><br><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n\n\n<h2 class=\"wp-block-heading\"><a><\/a> Assembling the matrix equation from the data<\/h2>\n\n\n\n<p>Inspecting the above sums, we see that we can accumulate them &#8220;on the fly&#8221;, as we read the input data file; so no need to create an <em>n<\/em> rows by 2 columns matrix, nor its transpose, nor an <em>n<\/em> row vector.<\/p>\n\n\n\n<p>Note as well that the matrix <em>X<\/em><sup><em>T<\/em><\/sup><em> X <\/em>is symmetric, that is the value in row 1 column 2 is the same as the value in row 2 column 1; so we only need to accumulate one of those; we&#8217;ll do that into row 1 column 2.<\/p>\n\n\n\n<p>So now we know how to accumulate the values in the matrix equation as we read them; but how do we solve the matrix equation to get the slope <em>m<\/em> and the y-intercept <em>b<\/em> of the line?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a><\/a>Solving the matrix equation<\/h2>\n\n\n\n<p>In a simple case like this, we can use <a href=\"https:\/\/en.wikipedia.org\/wiki\/Gaussian_elimination\"><u>Gaussian elimination<\/u><\/a>, followed by back substitution. That is, we determine a factor <em>a<\/em> that when row 1 values of <em>X<\/em><sup><em>T<\/em><\/sup><em> X<\/em> and <em>X<\/em><sup><em>T<\/em><\/sup><em><u>y<\/u><\/em> are muliplied by <em>a <\/em>and added to the values of row 2<em>, <\/em>the new value of <em>X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>1,1<\/em><\/sub> is zero.<\/p>\n\n\n\n<p>Therefore, the value of <em>a<\/em> needs to be calculated as<\/p>\n\n\n\n<p><em>a = -X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,1<\/em><\/sub><em> \u00f7 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>1,1<\/em><\/sub><\/p>\n\n\n\n<p>and we update the second row of <em>X<\/em><sup><em>T<\/em><\/sup><em> X<\/em> as follows<\/p>\n\n\n\n<p><em>X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,1 <\/em><\/sub><em>\u2190 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,1 <\/em><\/sub><em>+ a \u00b7 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>1,1<\/em><\/sub><em> = X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,1 <\/em><\/sub><em>\u2013 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,1 <\/em><\/sub><em>= 0<\/em><\/p>\n\n\n\n<p><em>X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,2 <\/em><\/sub><em>\u2190 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,2 <\/em><\/sub><em>+ a \u00b7 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>1,2<\/em><\/sub><\/p>\n\n\n\n<p>and the second element of <em>X<\/em><sup><em>T<\/em><\/sup> <em><em><u>y<\/u><\/em><\/em> as follows<\/p>\n\n\n\n<p><em>X<\/em><sup><em>T<\/em><\/sup> <em><em><u><em><u>y<\/u><\/em><sub><em>2<\/em><\/sub><\/u><\/em><\/em><sub><em> <\/em><\/sub><em>\u2190 <em>X<\/em><sup><em>T<\/em><\/sup><\/em> <em><em><em><u><em><u>y<\/u><\/em><sub><em>2<\/em><\/sub><\/u><\/em><\/em>+ a \u00b7 <em>X<\/em><sup><em>T<\/em><\/sup><\/em> <em><em><em><em><u><em><u>y<\/u><\/em><\/u><\/em><\/em><\/em><\/em><sub><em>1<\/em><\/sub><\/p>\n\n\n\n<p>At this point we can back substitute for the value of <em>b<\/em> by taking the dot product of the second row of<em> X<\/em><sup><em>T<\/em><\/sup><em> X <\/em>with the vector<em> [m,b] <\/em>to solve for<em> b<\/em><\/p>\n\n\n\n<p><em>0 \u00b7 m + X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,2 <\/em><\/sub><em>\u00b7 b = <em>X<\/em><sup><em>T<\/em><\/sup><\/em> <em><u>y<\/u><\/em><sub><em>2<\/em><\/sub><\/p>\n\n\n\n<p>and so<\/p>\n\n\n\n<p><em>b = <em>X<\/em><sup><em>T<\/em><\/sup><\/em> <em><em><u>y<\/u><\/em><sub><em>2<\/em><\/sub><\/em><sub><em> <\/em><\/sub><em>\u00f7 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,2<\/em><\/sub><\/p>\n\n\n\n<p>And then, knowing <em>b<\/em>, similarly with the dot product of the first row of <em>X<\/em><sup><em>T<\/em><\/sup><em> X <\/em>for <em>m<\/em><\/p>\n\n\n\n<p><em>X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>1,1<\/em><\/sub><em> \u00b7 m + X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,2<\/em><\/sub><em> \u00b7 b = <em>X<\/em><sup><em>T<\/em><\/sup><\/em> <em><em><em><u>y<\/u><\/em><\/em><\/em><sub><em>1<\/em><\/sub><\/p>\n\n\n\n<p>or<\/p>\n\n\n\n<p><em>m = <\/em>(<em>X<\/em><sup><em>T<\/em><\/sup> <em><em><em><u>y<\/u><\/em><\/em><\/em><sub><em>1<\/em><\/sub><em> \u2013 b \u00b7 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>2,2 <\/em><\/sub><em>)\u00f7 X<\/em><sup><em>T<\/em><\/sup><em> X<\/em><sub><em>1,1<\/em><\/sub><br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a><\/a> Never mind the formulas, let\u2019s see the code<\/h2>\n\n\n\n<p>As I began this article, I realized I forgot one small but important utility routine, in order to convert the STRING fields on the data records to REAL. Here it is:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     1\tPROC str to real = (STRING s) REAL:\n     2\tBEGIN\n     3\t    REAL v := 0.0, pt := 1.0, scale := 1.0;\n     4\t    BOOL negative := FALSE;\n     5\t    INT a0 = ABS \"0\";\n     6\t    FOR d FROM UPB s BY -1 TO LWB s DO\n     7\t        CHAR sd = s[d];\n     8\t        IF is digit(sd) THEN\n     9\t            v +:= (ABS sd - a0) * pt;\n    10\t            pt *:= 10.0\n    11\t        ELIF sd = \"-\" THEN\n    12\t            negative := TRUE\n    13\t        ELIF sd = \".\" THEN\n    14\t            scale := pt\n    15\t        FI\n    16\t    OD;\n    17\t    (negative | -v | v) \/ scale\n    18\tEND;<\/pre>\n\n\n\n<p>Nothing too crazy here. Worth emphasizing:<\/p>\n\n\n\n<p>This procedure returns a real value; hence the final expression &#8211; a conditional-clause in Algol 68 terms &#8211; yields a <code>REAL<\/code> value<\/p>\n\n\n\n<p>Algol 68 Genie only uses ASCII characters in names, so the numeric characters are therefore known to be contiguous and the corresponding integer value can be calculated by taking the ABS of the character minus <code>ABS \u201c0\u201d<\/code><\/p>\n\n\n\n<p>And finally, the least squares fitting code:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     1\t#\n     2\t    Utility routines\n     3\t#\n       \n     4\tPR read \"str_to_real.a68\" PR\n     5\tPR read \"split.a68\" PR\n     6\tPR read \"each_delimited_line.a68\" PR\n       \n     7\t#\n     8\t    Perform a least-squares fit of a line to a data file containing (x,y) values\n     9\t#\n       \n    10\tBEGIN\n       \n    11\t    [1:2,1:2] REAL xtx := ((0.0, 0.0),(0.0,0.0));\n    12\t    [1:2] REAL xty := (0.0, 0.0);\n       \n    13\t    # Accumulate XTX and XTy #\n       \n    14\t    each delimited line(\"test_data.txt\", \",\", (STRING line, []STRING fields, INT line count) VOID: BEGIN\n    15\t        # skip the header line #\n    16\t        IF line count &gt; 1 THEN\n    17\t            REAL xi = str to real(fields[1]), yi = str to real(fields[2]);\n    18\t            xtx[1,1] +:= xi * xi;\n    19\t            xtx[1,2] +:= xi;\n    20\t            xtx[2,2] +:= 1.0;\n    21\t            xty[1] +:= xi * yi;\n    22\t            xty[2] +:= yi\n    23\t        FI\n    24\t    END);\n    25\t    xtx[2,1] := xtx[1,2];\n       \n    26\t    # let's see the matrix and vector before Gauss #\n       \n    27\t    print((\"before Gauss:\",new line));\n    28\t    print((\"\u23a1\",xtx[1,1],\"   \",xtx[1,2],\"\u23a4  =  \u23a1\",xty[1],\"\u23a4\",new line));\n    29\t    print((\"\u23a3\",xtx[2,1],\"   \",xtx[2,2],\"\u23a6     \u23a3\",xty[2],\"\u23a6\",new line));\n       \n    30\t    # Gaussian elimination #\n       \n    31\t    REAL a = -xtx[2,1] \/ xtx[1,1];\n    32\t    xtx[2,1] +:= a * xtx[1,1];\n    33\t    xtx[2,2] +:= a * xtx[1,2];\n    34\t    xty[2] +:= a * xty[1];\n       \n    35\t    # let's see the matrix and vector after Gauss #\n       \n    36\t    print((\"after Gauss:\",new line));\n    37\t    print((\"\u23a1\",xtx[1,1],\"   \",xtx[1,2],\"\u23a4  =  \u23a1\",xty[1],\"\u23a4\",new line));\n    38\t    print((\"\u23a3\",xtx[2,1],\"   \",xtx[2,2],\"\u23a6     \u23a3\",xty[2],\"\u23a6\",new line));\n       \n    39\t    # back substitution #\n       \n    40\t    REAL b = xty[2] \/ xtx[2,2];\n    41\t    REAL m = (xty[1] - xtx[1,2] * b) \/ xtx[1,1];\n       \n    42\t    # let's see the equation #\n       \n    43\t    print((\"equation:\",new line));\n    44\t    print((\"y = \",fixed(m,0,7),\" * x + \",fixed(b,0,7),new line))\n       \n    45\tEND<\/pre>\n\n\n\n<p>Not too much new here, either, but worth mentioning:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I\u2019ve saved the utility procedures in files and I\u2019m using Algol 68 Genie\u2019s <code>read<\/code> <strong>pragmat<\/strong> to include them at compile time. Pragmats are Algol 68\u2019s mechanism for issuing directives to the compiler.<sup><a href=\"#sdfootnote1sym\" id=\"sdfootnote1anc\"><sup>1<\/sup><\/a><\/sup><\/li>\n\n\n\n<li>I\u2019ve used some Unicode characters to better symbolize the matrix and vector. This seems to be OK in Algol 68 Genie character strings\u2026 something I have to dig into a bit more.<\/li>\n\n\n\n<li>You\u2019ve seen this before, and maybe you\u2019ve made a mental note\u2026 but for example in line 40, you see a constant value <code>b<\/code> calculated from an expression that includes the values of variables at the time of declaration of the constant. For clarity:\n<ul class=\"wp-block-list\">\n<li>Algol 68 constants are therefore more like what we think of today as immutable values and unlike <code>#define<\/code> constants in C.<\/li>\n\n\n\n<li>the scope of all variables and constants lies within the enclosed-clause where they are declared, including within any other enclosed-clauses declared within. (Algol 68 Genie warns if you declare a procedure with parameters of the same name as constants or variables declared within the same enclosed-clause.)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Given that, in lines 11 and 12, we used a row display to initialize the matrix and vector, why can\u2019t we use a formula like <code>xtx +:= ((xi * xi, xi),(xi, 1.0))<\/code> to accumulate the matrix (and similarly for the vector)? The answer to this is both interesting and disappointing:\n<ul class=\"wp-block-list\">\n<li>We can, but..<\/li>\n\n\n\n<li>We would first have to define a <code>+:=<\/code> operator that takes a <code>REF [,]REAL<\/code> parameter and a <code>[,]REAL<\/code> parameter and returns a <code>[,]REAL <\/code>value, because that operator, operating on matrices, is not defined in the standard prelude.<\/li>\n\n\n\n<li>You might think that this seems a bit odd, perhaps \u201cnon-orthogonal\u201d, since the assignation <code>:=<\/code> seems to take all manner of expressions on its left- and right-hand sides, but it\u2019s worth reflecting that you are in essence defining a composite \u201cadd together two values and then assign\u201d operator that takes the same parameters; it&#8217;s the &#8220;add together&#8221; part, not the assignation itself that needs extending. And, let\u2019s just emphasize for now, the assignation <code>:=<\/code> is special in a few ways, including the fact that its right-hand side must be fully evaluated before being assigned to its left-hand side, whereas the arguments to dyadic operators in Algol 68 are evaluated collaterally, that is, in no particular order.<\/li>\n\n\n\n<li>This approach would be more compact but would also not take into account the symmetric nature of the matrix and therefore do an unnecessary accumulation. While this doesn\u2019t sound like much, if we are doing a regression with many independent variables, it starts to add up (for example, if we were fitting <em>z = a + bx + cy<\/em>, we would have a 3&#215;3 matrix). We could of course make a special version of \u201cplus and becomes\u201d that only builds the diagonal and upper right part of the matrix, but this does not smell like <code>+:=<\/code> to me.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Let\u2019s run the program:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ a68g regress.a68<br>before Gauss:<br>\u23a1+1.55925163017308e  +4   +2.59649902000000e  +3\u23a4  =  \u23a1+1.81890000036266e  +4\u23a4<br>\u23a3+2.59649902000000e  +3   +5.77000000000000e  +2\u23a6     \u23a3+3.17362830000000e  +3\u23a6<br>after Gauss:<br>\u23a1+1.55925163017308e  +4   +2.59649902000000e  +3\u23a4  =  \u23a1+1.81890000036266e  +4\u23a4<br>\u23a3+0.00000000000000e  +0   +1.44625453749719e  +2\u23a6     \u23a3+1.44757284553051e  +2\u23a6<br>equation:<br>y = .9998472 * x + 1.0009115<br>$<\/pre>\n\n\n\n<p>We know the equation of the original line was<\/p>\n\n\n\n<p><em>y = x + 1<\/em><\/p>\n\n\n\n<p>before we randomized the <em>y<\/em> values; so the coefficients <em>m<\/em> and <em>b<\/em> determined by the fit seem quite reasonable (each equal to one to four significant figures).<\/p>\n\n\n\n<p>We could calculate residuals and various statistical measures, but I&#8217;m going to leave that as an exercise for the interested reader.<\/p>\n\n\n\n<p>Now; wasn&#8217;t that more fun than <code>\"Hello world\"<\/code>?<\/p>\n\n\n\n<p>In the next article, we&#8217;ll write a pretty-printer that makes our Algol 68 code look the way it appears in reference material.<\/p>\n\n\n\n<p><a href=\"#sdfootnote1anc\" id=\"sdfootnote1sym\">1 <\/a><a href=\"https:\/\/jmvdveer.home.xs4all.nl\/learning-algol-68-genie.pdf\"><u>Learning Algol 68 Genie<\/u><\/a>, 9.7.2 Inclusion of files, p. 201.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In memory of J. Kevin Douglas, a good friend and fellow fan of Algol 68 In the previous<\/p>\n","protected":false},"author":430,"featured_media":3514,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[794,98,5,150],"tags":[783,152],"class_list":["post-11220","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-algol-68","category-code","category-linux","category-programming","tag-algol-68","tag-programming"],"modified_by":"David Both","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11220","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/430"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11220"}],"version-history":[{"count":4,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11220\/revisions"}],"predecessor-version":[{"id":11226,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11220\/revisions\/11226"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/3514"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11220"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11220"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11220"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}