{"id":6923,"date":"2024-08-10T03:00:00","date_gmt":"2024-08-10T07:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=6923"},"modified":"2024-08-07T12:26:25","modified_gmt":"2024-08-07T16:26:25","slug":"a-look-back-fortran-77","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=6923","title":{"rendered":"A look back: FORTRAN 77"},"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=\"6923\" 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>These days, a lot of programming languages look alike. You don\u2019t have to be a Rust programmer to read a Rust program and get a general idea about what it does. If you know a little C, or C++, or Java, or C#, or Go, \u2026 or any of a number of other \u201cC derived\u201d programming languages, you can probably read other \u201cC derived\u201d languages. These <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_C-family_programming_languages\">C-family programming languages<\/a> all use the semicolon (<code>;<\/code>) to end statements, parentheses (<code>()<\/code>) to isolate comparisons, curly braces (<code>{}<\/code>) for program blocks, standard symbols for comparison (such as <code>&lt;<\/code> for <em>less than<\/em>), and other language features.<\/p>\n\n\n\n<p>But programming languages haven\u2019t always looked like this.<\/p>\n\n\n\n<p>FORTRAN 77 provides an interesting view into programming languages of the past. Let\u2019s take a step back in time to look at how programmers created new programs using punched cards with FORTRAN 77. This isn\u2019t meant to be a deep dive, but a primer that provides an overview of FORTRAN 77, with a brief introduction for how to write your first programs in FORTRAN 77.<\/p>\n\n\n\n<p>To follow along, you\u2019ll need to install a FORTRAN compiler. The GNU Compiler Collection includes a very nice FORTRAN compiler, which you can install using the <strong>gcc-gfortran<\/strong> package:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo dnf install gcc-gfortran<\/code><\/pre>\n\n\n\n<p>I\u2019ll use old-style FORTRAN 77, which the GNU compiler may complain about. You can avoid these messages by passing the <code>-std=legacy<\/code> option to the compiler. On my system, I created this 2-line shell script called <code>f77<\/code> that does it for me:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\ngfortran -std=legacy \"$@\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"a-brief-history\">A brief history<\/h2>\n\n\n\n<p>In the now-distant origins of computing, programming languages were quite different. One venerable programming language &#8211; in fact, one of the earliest compiled languages &#8211; was FORTRAN, an acronym for <strong>FOR<\/strong>mula <strong>TRAN<\/strong>slation. FORTRAN looked and acted differently as a programming language because of the technology era in which it was born. FORTRAN programs were written on <em>punched cards<\/em> &#8211; literally, cards made from heavy paper and punched with holes, where each combination of holes represented a different character.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"767\" height=\"345\" src=\"https:\/\/www.both.org\/wp-content\/uploads\/2024\/08\/card-hello.png\" alt=\"\" class=\"wp-image-6924\"\/><\/figure>\n\n\n\n<p><a href=\"https:\/\/www.masswerk.at\/keypunch\/?b=aGVsbG8gd29ybGQh\">original image<\/a><\/p>\n\n\n\n<p>The first version of the FORTRAN programming language was conceived in the 1950s. FORTRAN was updated over time, including FORTRAN-II and FORTRAN-III in the late 1950s, FORTRAN-IV in the early 1960s, FORTRAN 66 in 1966, and FORTRAN 77 in 1977. Later versions of the language changed the spelling to <strong>Fortran<\/strong>, starting with Fortran 90 in 1990; the most recent Fortran standard is Fortran 2023. However, a modern Fortran compiler remains <em>backwards compatible<\/em> with earlier versions of the language, so you can still compile a FORTRAN 77 program using a more recent Fortran compiler.<\/p>\n\n\n\n<p>Throughout its development, FORTRAN was popular with scientists and engineers because the language made it easy to translate formulas and calculations into computer programs. For example, I learned FORTRAN 77 as an undergraduate physics student in the early 1990s; we used FORTRAN 77 because while the Fortran 90 standard was expected in 1990, it didn\u2019t get released until 1991, and compilers weren\u2019t available for some time after that.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"uppercase-and-80-columns\">Uppercase and 80 columns<\/h2>\n\n\n\n<p>The IBM Model 026 punched card was immensely popular since its introduction in July 1949. It was used pretty widely in businesses for data processing. And even though the character set was limited, it remained a popular medium for programming languages (like FORTRAN) into the early 1970s.<\/p>\n\n\n\n<p>The Model 026 had at least two common character sets: one was for commercial applications, the other was for FORTRAN programming. The main difference seems to be plus (<code>+<\/code>) in FORTRAN (<code>&amp;<\/code> in commercial) and equals (<code>=<\/code>) and single quote (<code>'<\/code>) and parentheses (<code>()<\/code>). I\u2019ll work with the FORTRAN character set here.<\/p>\n\n\n\n<p>Each character on a card was represented by a series of holes punched into the card, arranged in a column. By changing the order of these holes, you could define different characters. However, cards had a physical limit: if you punched too many holes too closely together, the card might easily tear. As a result, the Model 026 punched card defined the character set so that for any single letter, you didn\u2019t have two holes next to each other.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"767\" height=\"345\" src=\"https:\/\/www.both.org\/wp-content\/uploads\/2024\/08\/card-f77.png\" alt=\"\" class=\"wp-image-6925\"\/><\/figure>\n\n\n\n<p><a href=\"https:\/\/www.masswerk.at\/keypunch\/?b=IDAxMjM0NTY3ODkgYWJjZGVmZ2hpIGprbG1ub3BxciBzdHV2d3h5eg==&amp;c=fortran\">original image<\/a><\/p>\n\n\n\n<p>As a result, FORTRAN punched cards supported a character set containing only the numbers 0 to 9, uppercase letters A to Z, and a short list of special characters: space, equals (<code>=<\/code>), plus (<code>+<\/code>), minus (<code>-<\/code>), star (<code>*<\/code>), slash (<code>\/<\/code>), comma (<code>,<\/code>), period (<code>.<\/code>), apostrophe (<code>'<\/code>), dollar (<code>$<\/code>), colon (<code>:<\/code>), and left and right parentheses (<code>()<\/code>).<\/p>\n\n\n\n<p>Cards also had limited space, and FORTRAN had this same limitation. Of the 80 columns on a punched card, the last 8 columns were reserved for <em>card sorting<\/em>. If you dropped a stack of punched cards on the floor, you could load the cards into a card sorting machine, which would put the cards back into some semblance of order. New cards might come with the last 8 columns pre-punched with an increasing series of numbers, providing a default ordering.<\/p>\n\n\n\n<p>The first 5 columns were reserved for optional <em>statement labels<\/em>, or a <em>comment marker<\/em> if column 1 contained either <code>C<\/code> or <code>*<\/code>. That leaves 80 &#8211; 8 &#8211; 5 = 67 columns on each card, which isn\u2019t a lot of space to write a program instruction, especially a nontrivial one for a complicated program. To work around this limitation, FORTRAN reserved column 6 for a <em>continuation marker<\/em>, which was usually a number or a special symbol like <code>+<\/code>. The remaining <strong>66<\/strong> columns were for actual program statements. This allowed programmers to combine several cards to make one long FORTRAN statement.<\/p>\n\n\n\n<p>The columns will make more sense as we learn more about FORTRAN.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"hello-world\">Hello world<\/h2>\n\n\n\n<p>To start a FORTRAN 77 program, use the <code>PROGRAM<\/code> keyword, followed by the name of the program. The program name can be almost anything, as long as it isn\u2019t a keyword. However, if you call the program <code>COUNT<\/code>, then you can\u2019t have a variable in the program called <code>COUNT<\/code>. To avoid name collisions, I sometimes write my program name with a few zeroes tacked on the end.<\/p>\n\n\n\n<p>To end a program definition, use the <code>END<\/code> statement.<\/p>\n\n\n\n<p>You write your program between the <code>PROGRAM<\/code> and <code>END<\/code> statements. Let\u2019s get started by writing a simple \u201cHello world\u201d program. This requires just three statements:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM HELLO  \n      PRINT *, 'HELLO'\n      END<\/code><\/pre>\n\n\n\n<p>This uses the <code>PRINT<\/code> statement, which is a reserved FORTRAN statement. The <code>*<\/code> indicates a <em>format<\/em> statement to use, but we don\u2019t need to get into <em>formatted output<\/em> in this primer, so we\u2019ll just use <code>*<\/code> to tell FORTRAN to use some default formatting.<\/p>\n\n\n\n<p>Also notice how FORTRAN defines a string: it uses single quotes (<code>'<\/code>) around the word <code>HELLO<\/code>, instead of double quotes. The double quote (<code>\"<\/code>) didn\u2019t exist in the Model 026 punched card, so it wasn\u2019t available in the original FORTRAN character set.<\/p>\n\n\n\n<p>Save this as <code>hello.f<\/code> and compile it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o hello hello.f\n$ .\/hello\n HELLO<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"variables-and-values\">Variables and values<\/h2>\n\n\n\n<p>Programs are more useful if they can work with values in memory. These are called <em>variables<\/em>, and FORTRAN 77 provides several basic types, including <code>INTEGER<\/code> for counting numbers, <code>REAL<\/code> for floating point values, <code>DOUBLE PRECISION<\/code> for larger values, <code>COMPLEX<\/code> for numbers that contain an <em>imaginary<\/em> component like <em>1+2i<\/em>, and <code>CHARACTER<\/code> for letter values. Let\u2019s start by examining the <code>REAL<\/code> variable type with this program:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM REAL000\n      REAL X,Y\n      X=1.0\n      Y=2.0\n      PRINT *, X\n      PRINT *, Y\n      END<\/code><\/pre>\n\n\n\n<p>I\u2019ve named the program <code>REAL000<\/code> to \u201cpad out\u201d the name so it won\u2019t collide with the <code>REAL<\/code> keyword.<\/p>\n\n\n\n<p>While FORTRAN 77 supports an <code>IMPLICIT<\/code> rule where you might assume variables that start with <code>I<\/code> through <code>N<\/code> are integer values, and all other letters imply floating point variables, you can avoid a lot of programming headaches by defining the variables you need to use the data type they require. To define two floating point variables <code>X<\/code> and <code>Y<\/code>, I used the <code>REAL<\/code> keyword, then the names of the variables, separated by a comma.<\/p>\n\n\n\n<p>To assign values to these variables, make sure your number has a decimal point in it. The decimal point implies a floating point number; no decimal point suggests an integer value, and you cannot assign an integer value to a <code>REAL<\/code> variable. In this sample program, I was very explicit by writing <code>1.0<\/code> and <code>2.0<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o real real.f\n$ .\/real\n   1.00000000    \n   2.00000000<\/code><\/pre>\n\n\n\n<p>You might also notice that my program doesn\u2019t consistently use spaces everywhere. An interesting side effect of the limited space on a punched card is that FORTRAN 77 programs don\u2019t need spaces between keywords, variable names, and symbols. This feature allowed programmers to write long statements on a single card. For example, let\u2019s write essentially the same program using <code>DOUBLE PRECISION<\/code> variables, but without the spaces:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAMDBL000\n      DOUBLEPRECISIONX,Y\n      X=1.0\n      Y=2.0\n      PRINT*,X\n      PRINT*,Y\n      END<\/code><\/pre>\n\n\n\n<p>That may be hard for a human to read, but the FORTRAN compiler will recognize <code>PROGRAM<\/code> as a keyword, and <code>DBL000<\/code> as the name of the program. Similarly, the compiler will interpret <code>DOUBLEPRECISION<\/code> as <code>DOUBLE PRECISION<\/code>, and will understand that <code>X<\/code> is the name of the first variable.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o dbl dbl.f\n$ .\/dbl\n   1.0000000000000000     \n   2.0000000000000000<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conditional-evaluation\">Conditional evaluation<\/h2>\n\n\n\n<p>Like other programming languages, FORTRAN supports conditional evaluation using an <code>IF<\/code> statement. However, things get a little weird here. You might be used to testing values like <code>if (x&lt;2)<\/code> or <code>if (a&gt;b)<\/code>, but the FORTRAN character set doesn\u2019t include \u201cless than\u201d or \u201cgreater than\u201d characters. Instead, FORTRAN uses abbreviations for each of the comparisons:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Comp.<\/th><th>Meaning<\/th><\/tr><\/thead><tbody><tr><td><code>.LT.<\/code><\/td><td>Less than<\/td><\/tr><tr><td><code>.LE.<\/code><\/td><td>Less than or equal<\/td><\/tr><tr><td><code>.GT.<\/code><\/td><td>Greater than<\/td><\/tr><tr><td><code>.GE.<\/code><\/td><td>Greater than or equal<\/td><\/tr><tr><td><code>.EQ.<\/code><\/td><td>Equal to<\/td><\/tr><tr><td><code>.NE.<\/code><\/td><td>Not equal to<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>The dots around each abbreviation are part of the keyword, so don\u2019t forget to include them. Let\u2019s test each of these using a series of 1-line <code>IF<\/code> statements:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM IF000\n      IF (1.LT.2) PRINT *, '1 IS LESS THAN 2'\n      IF (2.GT.1) PRINT *, '2 IS GREATER THAN 1'\n      IF (3.EQ.3) PRINT *, '3 IS EQUAL TO 3'\n\n      IF (1.GE.0) PRINT *, '1 IS GREATER OR EQUAL TO 0'\n      IF (1.GE.1) PRINT *, '1 IS GREATER OR EQUAL TO 1'\n      IF (3.LE.2) PRINT *, 'SHOULD NOT SEE THIS'\n      IF (3.LE.3) PRINT *, '3 IS LESS THAN OR EQUAL TO 3'\n      END<\/code><\/pre>\n\n\n\n<p>All of these statements should generate output, except one. The exception is <code>3.LE.2<\/code>, because 3 is not less than or equal to 2. If you compile and run the sample program, you\u2019ll see the other statements print a message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o if if.f\n$ .\/if\n 1 IS LESS THAN 2\n 2 IS GREATER THAN 1\n 3 IS EQUAL TO 3\n 1 IS GREATER OR EQUAL TO 0\n 1 IS GREATER OR EQUAL TO 1\n 3 IS LESS THAN OR EQUAL TO 3<\/code><\/pre>\n\n\n\n<p>Logical expressions and tests evaluate to either <code>.TRUE.<\/code> or <code>.FALSE.<\/code> and can be combined with several <em>logical operators<\/em> like these:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Op.<\/th><th>Meaning<\/th><\/tr><\/thead><tbody><tr><td><code>.NOT.<\/code><\/td><td>Opposite value<\/td><\/tr><tr><td><code>.AND.<\/code><\/td><td>Both are true<\/td><\/tr><tr><td><code>.OR.<\/code><\/td><td>Either is true<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>We can see how FORTRAN uses these operators by writing a sample program:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM AND000\n      IF (.NOT. (1.LT.2)) PRINT *, 'SHOULD NOT SEE THIS'\n      IF ( (1.LT.2) .OR. (3.LT.2) ) PRINT *, '1 LT 2'\n      IF ( (1.LT.2) .AND. (1.LT.3) ) PRINT *, '1 LT 2 AND LT 3'\n      END<\/code><\/pre>\n\n\n\n<p>The first statement shouldn\u2019t generate any output, because 1 is less than 2, but this test is <em>negated<\/em>, so the <code>.TRUE.<\/code> value becomes a <code>.FALSE.<\/code> instead. However, the other two tests should print a message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o and and.f\n$ .\/and\n 1 LT 2\n 1 LT 2 AND LT 3<\/code><\/pre>\n\n\n\n<p>Early versions of FORTRAN supported only this 1-line <code>IF<\/code> statement. However, later versions of FORTRAN, such as FORTRAN 77, allowed <code>IF<\/code> statements to start a block of conditional execution. Use <code>IF(<\/code>\u2026<code>)THEN<\/code> to start a block, and end it with <code>END IF<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM IFTHEN0\n      IF ( (1.LT.2) .AND. (1.LT.3) ) THEN\n        PRINT *, '1 IS LESS THAN 2'\n        PRINT *, '1 IS LESS THAN 3'\n      END IF\n      END<\/code><\/pre>\n\n\n\n<p>The extra spaces are for clarity &#8211; but \u201cindenting\u201d statements was not often done in early FORTRAN programs because of the limited space on each punched card. Remember, a card could only hold 66 columns of source code, so space was at a premium. It might be more common to see this program written without spaces in FORTRAN 77:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM IFTHEN0\n      IF((1.LT.2).AND.(1.LT.3))THEN\n      PRINT*,'1 IS LESS THAN 2'\n      PRINT*,'1 IS LESS THAN 3'\n      ENDIF\n      END<\/code><\/pre>\n\n\n\n<p>Either way, the program generates the same output, because 1 is less than both 2 and 3:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o if-then if-then.f\n$ .\/if-then\n 1 IS LESS THAN 2\n 1 IS LESS THAN 3<\/code><\/pre>\n\n\n\n<p>You can also use an <code>ELSE<\/code> condition to do something else if the test fails:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM ELSE000\n      IF (1.GT.2) THEN\n        PRINT *, 'NOT TRUE'\n      ELSE\n        PRINT *, '1 IS NOT GREATER THAN 2'\n      ENDIF\n      END<\/code><\/pre>\n\n\n\n<p>The first test should never succeed; 1 is definitely <em>less than<\/em> 2, not greater than 2. So only the <code>ELSE<\/code> block should execute:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o else else.f\n$ .\/else\n 1 IS NOT GREATER THAN 2<\/code><\/pre>\n\n\n\n<p>For other tests in the same <code>IF<\/code> block, use the <code>ELSE IF<\/code> statement. This introduces another test where you can examine some other value. If you use <code>ELSE<\/code>, you should put it last:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM ELSEIF00\n      IF (1.GT.2) THEN\n        PRINT *, 'NOT TRUE'\n      ELSE IF (1.LT.2) THEN\n        PRINT *, '1 IS LESS THAN 2'\n      ELSE\n        PRINT *, 'NOT TRUE'         \n      ENDIF\n      END<\/code><\/pre>\n\n\n\n<p>In this program, only the <code>ELSE IF<\/code> should execute, because 1 is less than 2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o else-if else-if.f\n$ .\/else-if\n 1 IS LESS THAN 2<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"labels-loops-and-jumps\">Labels, loops, and jumps<\/h2>\n\n\n\n<p>A powerful feature of any programming language is the <em>loop<\/em>, where the program iterates a variable over a set of values while it performs tasks. In FORTRAN, that\u2019s the <code>DO<\/code> loop. To create a <code>DO<\/code> loop, you need to define the <em>start<\/em> and <em>end<\/em> values, and an optional <em>step<\/em> value.<\/p>\n\n\n\n<p>In other programming languages, you might use curly braces to define the block of statements to execute in the loop. But FORTRAN 77 doesn\u2019t have this concept. Instead, the <code>DO<\/code> loop also requires a <em>label<\/em> to define the last program statement in the loop. Labels are always numbers, and must be written in the first 5 columns of a line.<\/p>\n\n\n\n<p>Let\u2019s define a simple loop so you can see what I mean. This loop prints a list of numbers from 1 to 5:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM DOLOOP\n      INTEGER I\n      DO 10 I = 1, 5\n10    PRINT *, I\n      END<\/code><\/pre>\n\n\n\n<p>If we compile and run the program, we will see the loop starts at 1 and ends at 5. Because the program did not define a <em>step<\/em> value, the sequence counts up by 1:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o do do.f\n$ .\/do\n           1\n           2\n           3\n           4\n           5<\/code><\/pre>\n\n\n\n<p>To see the <em>step<\/em> value in action, let\u2019s modify the program to print the numbers from 1 to 9, but only every other number:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM DOLOOP\n      INTEGER I\n      DO 10 I = 1,10,2\n10    PRINT *, I\n      END<\/code><\/pre>\n\n\n\n<p>This version of the program starts at 1 but ends at 10, incrementing the <code>I<\/code> variable by 2 after each loop. But because it can only print odd numbers, the loop actually ends at 9:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o do do.f\n$ .\/do\n           1\n           3\n           5\n           7\n           9<\/code><\/pre>\n\n\n\n<p>The pseudocode for this FORTRAN 77 loop might look like this, if written in a C-like language:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (i = 1; i &lt; 10; i += 2) {\n  print i;\n}<\/code><\/pre>\n\n\n\n<p>While ending the <code>DO<\/code> loop on a program instruction is valid in FORTRAN 77, later editions of the language deprecated it because it can lead to subtle bugs if you\u2019re not careful. Starting with FORTRAN 77, programmers were encouraged to make the last statement in the loop a <code>CONTINUE<\/code> instruction &#8211; this is effectively a \u201cdo nothing\u201d instruction, but makes for more readable code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat do.f\n      PROGRAM DOLOOP\n      INTEGER I\n      DO 10 I = 1,10,2\n        PRINT *, I\n10    CONTINUE\n      END<\/code><\/pre>\n\n\n\n<p>FORTRAN 77 only supports the <code>DO<\/code> loop, which is effectively a <em>for<\/em> loop. If you need another kind of loop, such as a <em>while<\/em> loop, you need to \u201cbuild\u201d it yourself using a <code>GO TO<\/code> instruction. The <code>GO TO<\/code> is a <em>jump<\/em> instruction that picks up program execution at a specific line label. For example, we can rewrite the <code>DO<\/code> loop using an <code>IF<\/code> and a <code>GO TO<\/code> instruction, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM IFGOTO\n      INTEGER I\n      I = 1\n10    PRINT *, I\n      I = I + 1\n      IF (I.LE.5) GOTO 10\n      END<\/code><\/pre>\n\n\n\n<p>This program is a little longer than the <code>DO<\/code> loop, but it\u2019s still short enough to read: The program initializes the <code>I<\/code> variable to 1, then prints it. After incrementing the variable by 1, it checks if the value is less than or equal to 5. If it is, then it restarts the loop by jumping to the <code>PRINT<\/code> instruction. Otherwise, execution passes to the next instruction, which ends the program.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o if-goto if-goto.f\n$ .\/if-goto\n           1\n           2\n           3\n           4\n           5<\/code><\/pre>\n\n\n\n<p>While modern programmers tend to shy away from jump statements, the <code>GO TO<\/code> can be very useful in FORTRAN 77 programs. Let\u2019s write a simple but nontrivial program to demonstrate how to use the <code>GO TO<\/code> in a loop to simulate an object falling under gravity. Physics was a common application for FORTRAN programs, so it seems apt to demonstrate the <code>GO TO<\/code> with a physics equation of motion.<\/p>\n\n\n\n<p>For any moving object, you can track it\u2019s position over time using the equation:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><em>y<\/em>(<em>t<\/em>)\u2004=\u2004<em>y<\/em><sub>0<\/sub>\u2005+\u2005<em>v<\/em><sub>0<\/sub><em>t<\/em>\u2005+\u2005(1\/2)<em>at<\/em><sup>2<\/sup><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM FALL\n      REAL Y,V0,T,A\nC INITIALIZE VARIABLES\n      Y = 10.0\n      V0 = 0.0\n      A = 9.8\n      T = 0.0\nC SIMULATE A FALLING OBJECT UNDER GRAVITY\n10    Y = Y + V0 * T - .5 * A * T * T\n      PRINT *, T,Y\n      T = T + .1\n      IF (Y.GT.0.0) GOTO 10\n      END<\/code><\/pre>\n\n\n\n<p>I\u2019ve added a few comment lines so it\u2019s easier to follow along. Remember that a comment line starts with <code>C<\/code> or <code>*<\/code> in the first column. With these comments, it\u2019s easier to see that the program first initializes a set of variables (height <code>Y<\/code>, initial velocity <code>V0<\/code>, acceleration <code>A<\/code>, and time <code>T<\/code>) then enters a loop to iterate time by 0.1 seconds until the object\u2019s height is zero. At each step in the loop, the program prints the time and the height:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o fall fall.f\n$ .\/fall\n   0.00000000       10.0000000    \n  0.100000001       9.95100021    \n  0.200000003       9.75500011    \n  0.300000012       9.31400013    \n  0.400000006       8.52999973    \n  0.500000000       7.30499983    \n  0.600000024       5.54099989    \n  0.700000048       3.13999963    \n  0.800000072       3.99899483E-03\n  0.900000095      -3.96500182<\/code><\/pre>\n\n\n\n<p>This simulation shows that an object can fall 10 meters in just over 0.8 seconds. At that time, the height is <em>0.00399<\/em>, which is almost zero. The next iteration at 0.9 seconds sees the object at almost 4 meters underground.<\/p>\n\n\n\n<p>We can write a similar program to simulate a trajectory in two dimensions, also using the physics equation of motion. We\u2019ll use the assumption that there\u2019s no drag on the object, so the object\u2019s <em>x<\/em> velocity doesn\u2019t have a deceleration. That simplifies the <em>x<\/em> position as:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><em>x<\/em>(<em>t<\/em>)\u2004=\u2004<em>x<\/em><sub>0<\/sub>\u2005+\u2005<em>v<\/em><sub>0<\/sub><em>t<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM TRAJ\n      REAL X,X0,Y,Y0,T,A,V0,ANGLE\n      REAL PI\nC INITIALIZE VARIABLES\n      PI = 3.141459\n      Y0 = 0.0\n      X0 = 0.0\n      T = 0.1\n      A = 9.8\n      V0 = 5.0\n      ANGLE = 45.0\nC SIMULATE A TRAJECTORY\n10    Y = Y0 + V0*SIN(ANGLE*PI\/180.0) * T - .5 * A * T * T\n      X = X0 + V0*COS(ANGLE*PI\/180.0) * T\n      PRINT *, T,X,Y\n      T = T + .1\n      IF (Y.GT.0.0) GOTO 10\n      END<\/code><\/pre>\n\n\n\n<p>Because a trajectory requires an angle, this program uses the built-in trigonometry functions for <em>sin<\/em> and <em>cos<\/em>, converting the angle from degrees to radians using <em>r<\/em>\u2004=\u2004<em>\u03b8<\/em><em>\u03c0<\/em>\/180. If we compile and run the program, we can see an object fired at 5 <em>m\/s<\/em> at 45 degrees will travel just over 2.47 meters before it hits the ground:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o traj traj.f\n$ .\/traj\n  0.100000001      0.353565186      0.304541588    \n  0.200000003      0.707130373      0.511083126    \n  0.300000012       1.06069565      0.619624853    \n  0.400000006       1.41426075      0.630166292    \n  0.500000000       1.76782596      0.542707920    \n  0.600000024       2.12139130      0.357249618    \n  0.700000048       2.47495651       7.37910271E-02\n  0.800000072       2.82852173     -0.307667732<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"constant-values\">Constant values<\/h2>\n\n\n\n<p>The trajectory program used a value for <em>\u03c0<\/em> that is a known value, at about 3.14159. If the value won\u2019t change, you don\u2019t have to put it in a variable; instead, you can store it as a <code>PARAMETER<\/code>. Here is a simple example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM PI0000\n      PARAMETER(PI=3.14159)\n      PRINT *, PI\n      END<\/code><\/pre>\n\n\n\n<p>This is similar to using a <code>#define<\/code> in the C programming language. The parameter will look like any other variable, but you cannot change its value.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o pi pi.f\n$ .\/pi\n   3.14159012<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"reading-values\">Reading values<\/h2>\n\n\n\n<p>It would be nice to write a program <em>once<\/em> and run it multiple times with different values, where it prompts the user for the values each time, to see how the result changes. FORTRAN 77 has a companion to the <code>PRINT<\/code> statement, which prints values to the output; <code>READ<\/code> can interpret values from the user and store them in variables.<\/p>\n\n\n\n<p>To read a value, give the <code>READ<\/code> statement followed by a variable to store the result into. The <code>READ<\/code> statement will use the <code>*<\/code> <em>format<\/em> option to use the appropriate conversion; if you\u2019re using <code>READ<\/code> with an <code>INTEGER<\/code> variable, the value is stored as an integer, and so on.<\/p>\n\n\n\n<p>Let\u2019s demonstrate this by writing a short program to convert temperatures from Celsius to Fahrenheit. For any temperature <em>c<\/em>, we can find the temperature <em>f<\/em> using <em>f<\/em>\u2004=\u2004(9\/5)<em>c<\/em>\u2005+\u200532:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM FAHR\n      REAL F,C\n      PRINT *, 'ENTER TEMP IN C'\n      READ *, C\n      F = C * 9.0 \/ 5.0 + 32.0\n      PRINT *, C, 'CELCIUS IS', F, 'FAHRENHEIT'\n      END<\/code><\/pre>\n\n\n\n<p>If we compile this program, we can run it as many times as we need to convert several temperatures to Fahrenheit, such as the freezing and boiling points of water:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o fahr fahr.f\n$ .\/fahr\n ENTER TEMP IN C\n0\n   0.00000000     CELCIUS IS   32.0000000     FAHRENHEIT\n$ .\/fahr\n ENTER TEMP IN C\n100\n   100.000000     CELCIUS IS   212.000000     FAHRENHEIT<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"one-more-thing\">One more thing<\/h2>\n\n\n\n<p>I can\u2019t end the primer without showing a unique feature in FORTRAN 77: the <em>computed<\/em> <code>GO TO<\/code> statement. This is a very interesting construct that can be useful in the rare times that you need it, but otherwise a subtle way to add new bugs when you don\u2019t need to use it.<\/p>\n\n\n\n<p>The computed <code>GO TO<\/code> takes an integer variable and a list of line labels. If the variable has the value 1, then the <code>GO TO<\/code> jumps to the first label in the list. As you might guess, the computed <code>GO TO<\/code> jumps to the second label if the variable has the value 2. It gets tricky if the variable has a value less than 1, or if you have fewer labels in the list than the value.<\/p>\n\n\n\n<p>We can use the computed <code>GO TO<\/code> to calculate the Collatz Conjecture. The Collatz algorithm says for any positive <em>even<\/em> number, divide by 2; for any <em>odd<\/em> value, multiply by 3 and add 1. Collatz proposes that this simple algorithm will always result in 1 as the final value.<\/p>\n\n\n\n<p>To determine if a value is odd or even, we can use the <em>modulo<\/em> function, which returns the remainder after division. The <em>modulo<\/em> of <em>n<\/em>\/2 will be 0 if the number is even, and 1 if the number is odd. If we add 1 to the <em>modulo<\/em>, we\u2019ll have 1 if even and 2 if odd. That\u2019s a good use case for the computed <code>GO TO<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM COLLATZ\n      INTEGER N,M\nC GET NUMBER\n10    PRINT *, 'ENTER STARTING VALUE'\n      READ *, N\n      IF (N.LT.1) THEN\n        PRINT *, 'CANNOT BE LESS THAN 1'\n        GOTO 10\n      END IF\nC COLLATZ STARTS HERE\n20    PRINT *, N\n      IF (N.EQ.1) GOTO 50\n      M = MOD(N,2) + 1\n      GO TO (30,40), M\n30    N = N \/ 2\n      GO TO 20\n40    N = 3 * N + 1\n      GO TO 20\n50    END<\/code><\/pre>\n\n\n\n<p>If we compile and run the program, we can see that at least the numbers 1, 2, and 3 eventually fall to 1:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o collatz collatz.f\n$ .\/collatz\n ENTER STARTING VALUE\n0\n CANNOT BE LESS THAN 1\n ENTER STARTING VALUE\n1\n           1\n$ .\/collatz\n ENTER STARTING VALUE\n2\n           2\n           1\n$ .\/collatz\n ENTER STARTING VALUE\n3\n           3\n          10\n           5\n          16\n           8\n           4\n           2\n           1<\/code><\/pre>\n\n\n\n<p>While this is a neat demonstration of the computed <code>GO TO<\/code>, most programs will benefit from using some other arrangement. For example, the Collatz program can be written much simpler without the computed <code>GO TO<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PROGRAM COLLATZ\n      INTEGER N\nC GET NUMBER\n10    PRINT *, 'ENTER STARTING VALUE'\n      READ *, N\n      IF (N.LT.1) THEN\n      PRINT *, 'CANNOT BE LESS THAN 1'\n      GOTO 10\n      ENDIF \nC COLLATZ STARTS HERE\n20    PRINT *, N\n      IF (N.EQ.1) GOTO 50\n      IF (MOD(N,2).EQ.0) THEN\n        N=N\/2\n      ELSE\n        N=3*N+1\n      ENDIF \n      GOTO 20\n50    END<\/code><\/pre>\n\n\n\n<p>This uses an <code>IF<\/code>\u2026<code>ELSE<\/code> block to perform <em>n<\/em>\/2 for even numbers, and 3<em>n<\/em>\u2005+\u20051 for odd numbers. The blocks make the program\u2019s flow more clear, and gives the same output without using a computed <code>GO TO<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f77 -o collatz2 collatz2.f\n$ .\/collatz2 \n ENTER STARTING VALUE\n0\n CANNOT BE LESS THAN 1\n ENTER STARTING VALUE\n3\n           3\n          10\n           5\n          16\n           8\n           4\n           2\n           1<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"more-to-explore\">More to explore<\/h2>\n\n\n\n<p>This is just a primer to the FORTRAN 77 language to create programs. There\u2019s more to the language than just what I\u2019ve shown here &#8211; but now that you have the basics, you should be able to create useful programs to solve a variety of problems.<\/p>\n\n\n\n<p>To learn more, Oracle provides a free online <a href=\"https:\/\/docs.oracle.com\/cd\/E19957-01\/805-4939\/index.html\">language reference guide<\/a> that provides an excellent description of FORTRAN 77. Skip ahead to the <a href=\"https:\/\/docs.oracle.com\/cd\/E19957-01\/805-4939\/6j4m0vnc8\/index.html\">intrinsic functions<\/a> for a list of functions that are built into the FORTRAN 77 standard library. You can also use this guide to learn about more advanced features of FORTRAN 77, including arrays, functions, subroutines, files, and formatted input and output.<\/p>\n\n\n\n<p>The GNU Compiler Collection also has the GFortran documentation available in their <a href=\"https:\/\/gcc.gnu.org\/onlinedocs\/\">online documentation collection<\/a>. Make sure to match the version number of the documentation to the version of GFortran that you have installed on your system. You can check what version you have installed with the <code>--version<\/code> option:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gfortran --version\nGNU Fortran (GCC) 14.2.1 20240801 (Red Hat 14.2.1-1)\nCopyright (C) 2024 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.<\/code><\/pre>\n\n\n\n<p>In this case, I have GFortran 14.2, and you can find the <a href=\"https:\/\/gcc.gnu.org\/onlinedocs\/gcc-14.2.0\/gfortran\/\">GFortran 14.2 documentation<\/a> via this direct link.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Take a step back in time to a time when programs were punched on cards.<\/p>\n","protected":false},"author":33,"featured_media":3514,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[106,150],"tags":[522,316,152],"class_list":["post-6923","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-history","category-programming","tag-fortran77","tag-history","tag-programming"],"modified_by":"David Both","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/6923","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\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6923"}],"version-history":[{"count":2,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/6923\/revisions"}],"predecessor-version":[{"id":6927,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/6923\/revisions\/6927"}],"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=6923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}