{"id":14481,"date":"2026-08-03T01:00:00","date_gmt":"2026-08-03T05:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=14481"},"modified":"2026-07-27T13:48:13","modified_gmt":"2026-07-27T17:48:13","slug":"teaching-fortran-new-tricks","status":"publish","type":"post","link":"http:\/\/www.both.org\/?p=14481","title":{"rendered":"Teaching FORTRAN new tricks"},"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=\"14481\" 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 class=\"wp-block-paragraph\">I learned the FORTRAN programming language in the early 1990s when I was an undergraduate physics student. Back then, many physics students and physicists wrote FORTRAN programs to analyze lab data. FORTRAN made it easy because the language was designed to support mathematics and numerical simulation; the name \u201cFORTRAN\u201d stands for <strong>for<\/strong>mula <strong>tran<\/strong>slation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">FORTRAN has changed a lot over the years, although it wasn\u2019t until 1990 with \u201cFortran 90\u201d that the language looked considerably different. The version I learned was \u201cFORTRAN 77,\u201d which was standardized in 1977. This version of the language still retained its <a href=\"https:\/\/en.wikipedia.org\/wiki\/Punched_card\">punched card<\/a> roots, with strict column rules. But FORTRAN 77 was very useful for writing programs to analyze lab data or perform numerical simulations; not every lab could be analyzed with a spreadsheet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">While I wrote a lot of FORTRAN programs in my undergraduate days, I haven\u2019t really done much with it since then. But every once in a while, I like to go back and remind myself what you could do with FORTRAN.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Recently, there\u2019s been some interest in \u201cretro-programming\u201d with old DOS compilers, such as the ones that we include in the <a href=\"https:\/\/www.freedos.org\/\">FreeDOS Project<\/a>. I thought I\u2019d get into that challenge, and I decided to write a few new programs using Open Watcom FORTRAN 77, on FreeDOS.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Mandelbrot Set<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">One thing that FORTRAN makes easy is working with <a href=\"https:\/\/en.wikipedia.org\/wiki\/Complex_number\">complex numbers<\/a>, which is a two-part number that has both a <em>real<\/em> part and an <em>imaginary<\/em> part, like 3\u2005+\u20052<em>i<\/em>, where 3 is the real part and 2 is the imaginary part (the <em>i<\/em> means \u201cimaginary\u201d). Complex numbers get used a lot in physics and upper-level mathematics, so it\u2019s probably not a surprise that FORTRAN comes with a <code>COMPLEX<\/code> data type.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One interesting demonstration of complex numbers is the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Mandelbrot_set\">Mandelbrot Set<\/a>. This is a kind of \u201cfractal mathematics.\u201d I don\u2019t want to get too deep into the mathematics here, but a simple explanation of the Mandelbrot Set is that it represents a \u201cmap\u201d of the equation <em>z<\/em>\u2004=\u2004<em>z<\/em><sup>2<\/sup>\u2005+\u2005<em>c<\/em>, where both <em>z<\/em> and <em>c<\/em> are complex numbers. Each \u201cpoint\u201d or \u201cpixel\u201d in the Mandelbrot Set image shows a different value of <em>c<\/em>, where the real part of the complex number is on the <em>x<\/em> axis, and the imaginary part is on the <em>y<\/em> axis. If you calculate a value of <em>z<\/em>, you can <em>run the calculation again and again<\/em> to see what happens. If the value of <em>z<\/em> \u201csettles down,\u201d then you make a black dot or pixel in the image. If the value of <em>z<\/em> gets too big, then you make a colored pixel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That means drawing the Mandelbrot Set is really just a matter of working through all the values of <em>c<\/em> that you want to show, calculating <em>z<\/em>\u2004=\u2004<em>z<\/em><sup>2<\/sup>\u2005+\u2005<em>c<\/em> over and over to see what happens, and painting a pixel on the screen for that <em>c<\/em> value. Then you move on to the next value of <em>c<\/em> and do it again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, this sample program calculates the Mandelbrot Set, although it doesn\u2019t print anything so you can\u2019t see it. We can add that in the next step:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      PARAMETER(STEP=.005,LIMIT=100)\n      REAL DIST\n      REAL R,I\n      COMPLEX Z,C\n      INTEGER X,Y\n      INTEGER COUNT\n\n      Y=0\n      DO 100 I=1.0,-1.0,-STEP\n      Y=Y+1\n      \n      X=0\n      DO 100 R=-2.0,1.0,STEP\n      X=X+1\n      \n      C=CMPLX(R,I)\n      Z=CMPLX(0.0,0.0)\n      COUNT=0\n\n10    Z=Z**2+C\n\n      DIST=REAL(Z)**2 + IMAG(Z)**2\n      COUNT=COUNT+1\n      IF ((DIST.LT.4.0).AND.(COUNT.LT.LIMIT)) GOTO 10\n\n100   CONTINUE\n\n      END<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can see several features of the FORTRAN language here, such as how the <code>DO<\/code> loop iterates over a set of values. This also starts with <code>REAL<\/code> numbers for the <em>x<\/em> and <em>y<\/em> axes, and converts these to <code>COMPLEX<\/code> values using the <code>CMPLX<\/code> function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This program only calculates numbers, but doesn\u2019t do anything with the results. To do that, we need a way to draw pixels on the screen to represent if the <em>z<\/em>\u2004=\u2004<em>z<\/em><sup>2<\/sup>\u2005+\u2005<em>c<\/em> calculation stays within a range, or if the value grows too big.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Graphics in FORTRAN<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The FORTRAN programming language doesn\u2019t have any native support for graphics. It\u2019s an old language that was created long before video terminals. But different FORTRAN compilers might provide some extensions or libraries to create graphics from a FORTRAN program, and that\u2019s just what Open Watcom did.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using the Open Watcom FORTRAN 77 graphics library requires including two statements at the start of a program that needs to draw graphics:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      INCLUDE 'GRAPHAPI.FI'\n      INCLUDE 'GRAPH.FI'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">I should emphasize that these libraries are <em>not<\/em> standard FORTRAN, but an extension to the language provided by the Open Watcom FORTRAN 77 compiler. Compiler-specific extensions are not uncommon, and were actually <em>very common<\/em> in the 1980s and 1990s to support specific features like graphics on DOS, so it\u2019s not surprising that Open Watcom provides a graphics library on their DOS version of the FORTRAN 77 compiler.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Open Watcom graphics extensions all use an underscore in front of the routine name. The underscore is actually not part of the FORTRAN 77 character set, but Open Watcom used it to denote their extended libraries. For example, to set the graphics mode, you call the <code>_SETVIDEOMODE<\/code> routine with the video mode to use (like <code>_TEXTC80<\/code> to use color text or <code>_VRES16COLOR<\/code> to use VGA graphics).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After entering graphics mode, you can put individual pixels on the screen using the <code>_SETPIXEL<\/code> routine, and change the pixel color using the <code>_SETCOLOR<\/code> routine. Open Watcom supports other routines to do other things in graphics mode, like drawing rectangles, ellipses, and lines, but drawing pixels is all we need to generate the Mandelbrot Set in a FORTRAN program.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s update the FORTRAN program to not just calculate the Mandelbrot Set, but to draw a pixel on the screen for each value of <em>c<\/em>. If the <em>z<\/em>\u2004=\u2004<em>z<\/em><sup>2<\/sup>\u2005+\u2005<em>c<\/em> calculation \u201csettles down\u201d (stays within a certain <em>absolute value<\/em>) then we\u2019ll draw a black pixel for that value of <em>c<\/em>, where <code>R<\/code> is the <em>x<\/em> coordinate and <code>I<\/code> is the <em>y<\/em> coordinate. If the calculation instead grows too big, we\u2019ll draw a colored pixel on the screen. We can also do a little math to show a different color to indicate how quickly this value grew out of control: blue for \u201cvery fast\u201d and other colors for \u201cnot as quickly.\u201d<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The full program now looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      INCLUDE 'GRAPHAPI.FI'\n      INCLUDE 'GRAPH.FI'\n\n      PARAMETER(STEP=.005,LIMIT=100)\n      REAL DIST\n      REAL R,I\n      COMPLEX Z,C\n      INTEGER X,Y\n      INTEGER COUNT\n      \n      CALL _SETVIDEOMODE(_VRES16COLOR)\n\n      Y=0\n      DO 100 I=1.0,-1.0,-STEP\n      Y=Y+1\n      \n      X=0\n      DO 100 R=-2.0,1.0,STEP\n      X=X+1\n      \n      C=CMPLX(R,I)\n      Z=CMPLX(0.0,0.0)\n      COUNT=0\n\n10    Z=Z**2+C\n\n      DIST=REAL(Z)**2 + IMAG(Z)**2\n      COUNT=COUNT+1\n      IF ((DIST.LT.4.0).AND.(COUNT.LT.LIMIT)) GOTO 10\n\n      CALL _SETCOLOR(1 + COUNT\/10)\n      IF (COUNT.EQ.100) CALL _SETCOLOR(_BLACK)\n      CALL _SETPIXEL(X,Y)\n100   CONTINUE\n\n      PAUSE\n      CALL _SETVIDEOMODE(_DEFAULTMODE)\n      \n      PRINT 900, X,Y\n900   FORMAT(I3,1HX,I3)\n      END<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Drawing the Mandelbrot Set<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Save this as a new source file called <code>mand.f<\/code> on a FreeDOS system, then compile it with the Open Watcom FORTRAN 77 compiler, using the <strong>wfl<\/strong> command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt; WFL mand.f<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After a moment, you will have a program called <code>mand.exe<\/code> that you can run. This generates an image that\u2019s about 600 pixels wide and about 400 pixels tall, on a 640&#215;480 resolution VGA screen.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"480\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2026\/07\/mandelbrot-vga.png\" alt=\"black swirls on a blue background, width green highlight around the edges\" class=\"wp-image-14480\"\/><figcaption class=\"wp-element-caption\">The Mandelbrot Set, in VGA<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Here\u2019s an experiment in using the Open Watcom FORTRAN graphics library<\/p>\n","protected":false},"author":33,"featured_media":2814,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":"","_members_access_role":[],"_members_access_error":""},"categories":[798,340,150],"tags":[267,152],"class_list":["post-14481","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fortran-77","category-freedos","category-programming","tag-freedos","tag-programming"],"modified_by":"Jim Hall","_links":{"self":[{"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14481","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=14481"}],"version-history":[{"count":4,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14481\/revisions"}],"predecessor-version":[{"id":14498,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14481\/revisions\/14498"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/2814"}],"wp:attachment":[{"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14481"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14481"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14481"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}