Multiplication tables using implicit DO loops

While sorting through some old FORTRAN notes I found what amounted to a one line program, which was included as a minimalistic example of what could be achieved using implicit DO loops.

I thought it might be ‘fun’ to see if I could still get it (and some other examples) to compile and run. I remember that at the time I had to use FORTRAN, implicit DO loops were one of the things caused me a great deal of trouble – despite the simplicity of the following example.

      PROGRAM TIMES
      WRITE(6,‘(12(2X,I4))’) (((I*J),J=1,12),I=1,12)
      END

Which produced the output below.

    1     2     3     4     5     6     7     8     9    10    11    12
    2     4     6     8    10    12    14    16    18    20    22    24
    3     6     9    12    15    18    21    24    27    30    33    36
    4     8    12    16    20    24    28    32    36    40    44    48
    5    10    15    20    25    30    35    40    45    50    55    60
    6    12    18    24    30    36    42    48    54    60    66    72
    7    14    21    28    35    42    49    56    63    70    77    84
    8    16    24    32    40    48    56    64    72    80    88    96
    9    18    27    36    45    54    63    72    81    90    99   108
   10    20    30    40    50    60    70    80    90   100   110   120
   11    22    33    44    55    66    77    88    99   110   121   132
   12    24    36    48    60    72    84    96   108   120   132   144

The Rosetta Code project website also uses the problem of printing out a multiplication table as one of the examples that show how to solve a selection of programming tasks using different programming languages.

Using the Fortran 90 example as a starting point I decided to see how difficult it might be to solve this problem using VAX FORTRAN.  Having done that and managed to come up with a solution that worked using compiler that was only about 15 years old I decided to see it I could do the same using the oldest version of Fortran I have, Microsoft’s FORTRAN-80 compiler for CP/M as this seemed like an excellent excuse for some more retrocomputing fun.

Based on the copyright date in the manual this was first released in 1979 and I brought my copy in about 1984 but even then the actual software was still provided on an 8″ floppy disk which is about the same size as a mouse mat!

I now realize that the problems I used to have weren’t really due to the language, but were caused by the documentation and my lack of experience…

VAX FORTRAN

Though VAX FORTRAN is a FORTRAN-77 compiler I decided to go completely retro and used the ‘/NOF77’ option to allow it to compile programs written in FORTRAN-66. I quickly ran into a bit of a problem with the format specifiers used in the original example and by the time I finished getting it to work I understood how the FORMAT command worked in much more detail than when I started, and probably a lot more than the last time I used FORTRAN.  I also added the ability to change the number of times tables printed as well.

      PROGRAM TIMES
      IMPLICIT NONE
C
C     Produce a formatted multiplication table of the kind memorised by rote
C     when in primary school. Only print the top half triangle of products.
C
C     See <rosettacode.org/wiki/Multiplication_tables>
C
C     This program is free software: you can redistribute it and/or modify
C     it under the terms of the GNU General Public License as published by
C     the Free Software Foundation, either version 3 of the License, or (at
C     your option) any later version.
C
C     This program is distributed in the hope that it will be useful, but
C     WITHOUT ANY WARRANTY; without even the implied warranty of
C     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
C     General Public License for more details.
C
C     You should have received a copy of the GNU General Public License
C     along with this program.  If not, see <http://www.gnu.org/licenses/>

C
C     23 Nov 15 - 0.1   - Adapted from original for VAX FORTRAN - MEJT
C
      INTEGER I,J,K
      CHARACTER*32 S
C
C     Define the number of times tables to print.(Note - K must be in the
C     range one to twenty five.)
C
      K=12
C
C     Print a heading and underline it.
C
      WRITE(S,1) K,K
    1 FORMAT(8H(4H   |,,I2.2,11HI4,/,4H --+,I2.2,9H(4H----)))
      WRITE(6,S) (I,I = 1,K)
C
C     Print the rest of the table. For each row update the format string to
C     include the required number of leading blanks, since we can’t have
C     zero blanks in the first row start with one and compensate for the
C     extra space by reducing the width of the first number in each row of
C     the table by one…  
C
C     Not all compilers allow the use of a zero width integer field to
C     an integer field without leading spaces, using a fixed width field
C     with leading zeros solves this problem.
C
C
      DO 3 I=1,K
        WRITE(S,2) (I-1)*4+1,K
    2   FORMAT(12H(1H ,I2,1H|,,I2.2,5HX,I3,,I2.2,3HI4),8X)
C
C     Print the row with the desired number of leading spaces.
C
        WRITE(6,S) I,(I*J, J = I,K)
    3 CONTINUE
C
      END

If it works properly then it should produce the output below.  The program will also compile on a modern Linux system using gFortran but this outputs the carriage control characters, so you get an extra space at the beginning of each line.

  |   1   2   3   4   5   6   7   8   9  10  11  12
--+------------------------------------------------
 1|   1   2   3   4   5   6   7   8   9  10  11  12
 2|       4   6   8  10  12  14  16  18  20  22  24
 3|           9  12  15  18  21  24  27  30  33  36
 4|              16  20  24  28  32  36  40  44  48
 5|                  25  30  35  40  45  50  55  60
 6|                      36  42  48  54  60  66  72
 7|                          49  56  63  70  77  84
 8|                              64  72  80  88  96
 9|                                  81  90  99 108
10|                                     100 110 120
11|                                         121 132
12|                                             144


Microsoft FORTRAN-80

This solution depends on the use of the BYTE data type which is I think a non-standard feature of the Microsoft FORTRAN-80 compiler.

I developing the solution below I encountered a number of little quirks; you can use Hollerith strings to define values in a DATA statement but the length of each string must match the size of the data type, which means in this case each letter must be a separate string; and the default file numbers used are different.

      PROGRAM TIMES
C
C     Produce a formatted multiplication table of the kind memorised by rote
C     when in primary school. Only print the top half triangle of products.
C
C     This program is free software: you can redistribute it and/or modify
C     it under the terms of the GNU General Public License as published by
C     the Free Software Foundation, either version 3 of the License, or (at
C     your option) any later version.
C
C     This program is distributed in the hope that it will be useful, but
C     WITHOUT ANY WARRANTY; without even the implied warranty of
C     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
C     General Public License for more details.
C
C     You should have received a copy of the GNU General Public License
C     along with this program.  If not, see <http://www.gnu.org/licenses/>

C
C     23 Nov 15 - 0.1   - Adapted from original for VAX FORTRAN - MEJT
C     24 Nov 15 - 0.2   - FORTRAN IV version adapted from VAX FORTRAN and
C                         compiled using Microsoft FORTRAN-80 - MEJT
C     25 Nov 15 - 0.3   - Modified to use a BYTE array, which makes it much
C                         easier to understand what is going on.  However,
C                         I think this is a Microsoft language extension and
C                         isn’t strictly compliant with the FORTRAN IV
C                         language standard  - MEJT
C
C     Use an array of BYTE data to hold the format specifier string, and an
C     integer array to hold the intermediate results.
C
      BYTE A
      DIMENSION A(24)
      DIMENSION K(12)
C
C     When using Hollerith strings to define values in a DATA statement the
C     size of the strings must match the size of the data type - in this
C     case each string can be only a single byte in length.
C
      DATA A/‘(‘,‘1’,‘H’,‘ ‘,‘,’,‘I’,‘2’,‘,’,‘1’,‘H’,‘|’,‘,’,
     +       ‘0’,‘1’,‘X’,‘,’,‘I’,‘3’,‘,’,‘1’,‘1’,‘I’,‘4’,‘)’/
C
C     Print a heading and underline it.
C
      WRITE(1,1) (I,I=1,12)
    1 FORMAT(4H   |,12I4,/,4H --+12(4H----))
C
C     Print the rest of the table. For each row update the format string to
C     include the required number of leading blanks, since we can’t have
C     zero blanks in the first row start with one and compensate for the
C     extra space by reducing the width of the first number in each row of
C     the table by one…  
C
      DO 3 I=1,12
         A(13)=48+((I*4-3)/10)
         A(14)=48+(I*4-3)-((I*4-3)/10)*10
C
C        Uncomment the following two lines to print the format specifier
C        each time it is modified.
C
C        WRITE(1,4) (A(J), J = 1,24)
C    4   FORMAT(1x,24A1)
C
        DO 2 J=1,12
          K(J)=I*J
    2   CONTINUE
        WRITE(1,A)I,(K(J), J = I,12)
    3 CONTINUE
C
      END

If you didn’t want to use the BYTE data type you could solve the problem by storing the format specifier in a REAL array and overlaying this with an INTEGER array using and EQUIVALENCE statement.

      PROGRAM TIMES
C
C     Produce a formatted multiplication table of the kind memorised by rote
C     when in primary school. Only print the top half triangle of products.
C
C     This program is free software: you can redistribute it and/or modify
C     it under the terms of the GNU General Public License as published by
C     the Free Software Foundation, either version 3 of the License, or (at
C     your option) any later version.
C
C     This program is distributed in the hope that it will be useful, but
C     WITHOUT ANY WARRANTY; without even the implied warranty of
C     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
C     General Public License for more details.
C
C     You should have received a copy of the GNU General Public License
C     along with this program.  If not, see <http://www.gnu.org/licenses/>

C
C     23 Nov 15 - 0.1   - Adapted from original for VAX FORTRAN - MEJT
C     24 Nov 15 - 0.2   - FORTRAN IV version adapted from VAX FORTRAN and
C                         compiled using Microsoft FORTRAN-80 - MEJT
C
      DIMENSION K(12)
      DIMENSION A(6)
      DIMENSION L(12)
C
      COMMON //A
      EQUIVALENCE (A(1),L(1))
C
C     When using Hollerith strings to define values in a DATA statement the
C     size of the strings must match the size of the data type - in this
C     case each string must be four bytes in length as this is the size of a
C     REAL.
C
      DATA A/‘(1H ‘,‘,I2,’,‘1H|,’,’01X,’,‘I3,1’,‘2I4)’/
C
C     Print a heading and (try to) underline it.
C
      WRITE(1,1) (I,I=1,12)
    1 FORMAT(4H0  |,12I4,/,4H --+12(4H----))
C
C     Print the rest of the table. For each row update the format string to
C     include the required number of leading blanks, since we can’t have
C     zero blanks in the first row start with one and compensate for the
C     extra space by reducing the width of the first number in each row of
C     the table by one…  
C
C     Overlaying the format specifier with an integer array makes it possible
C     to modify the number of blank spaces.  The number of blank spaces is
C     stored as two consecutive ASCII characters that are in the same place
C     in memory as the integer value in L(7) in the order low byte, high
C     byte.
C
      DO 3 I=1,12
        L(7)=(48+(I*4-3)-((I*4-3)/10)*10)*256+48+((I*4-3)/10)
        DO 2 J=1,12
          K(J)=I*J
    2   CONTINUE
        WRITE(1,A)I,(K(J), J = I,12)
    3 CONTINUE
C
      END


This entry was posted in Linux, Retrocomputing, VMS and tagged , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s