FORTRAN IV was a major change from FORTRAN II. Not only did it introduce several new features, but there were several incompatibilities between FORTRAN IV and FORTRAN II.
Function names no longer ended in F, and a function returned an integer value (by default) if it began with a letter from I through N, rather than the letter X, following the same rules as variables.
Variables could be explicitly given a type by a type declaration statement. Arrays could also be dimensioned in these statements, so that a separate DIMENSION statement would not be required, and variables could be initialized in those statements, so that a separate DATA statement, also a new statement for FORTRAN IV, would not be required.
Character strings in FORMAT statements could be enclosed in single quotes, rather than it being necessary to count the characters in them for the former syntax of a Hollerith format specification.
Explicitly declaring the type of variables allowed variables to be declared as DOUBLE PRECISION, LOGICAL, or COMPLEX.
The LOGICAL data type could only have two values, .TRUE. or .FALSE., and corresponded to the type of a relational expression in a logical IF statement. Thus, instead of writing
IF (X-Y) 10,20,10
10 CONTINUE
it was now possible to write
IF (X .NE. Y) GO TO 20
The form of input-output statements was changed in FORTRAN IV as well. Instead of special purpose statements such as READ, PRINT, PUNCH, READ INPUT TAPE, and WRITE OUTPUT TAPE, there was simply READ (device, format) and WRITE (device, format). However, the BACKSPACE and REWIND statements continued to be available.
Also, the NAMELIST statement was provided, allowing list-directed input/output; on input, the variables to be changed could be indicated by name.
Functions and subroutines replaced the special statements that dealt with the sense switches and sense lights, as well as those that provided trapping of overflow and related conditions.
One important additional feature of FORTRAN IV was the ability to pass a function or subroutine to another function or subroutine as an argument. This meant, for example, that one could write a subroutine that did numerical integration, and pass to it the function to be integrated. This feature worked like this:
EXTERNAL FUN
X=ANUMIN(FUN,0.0,1.0)
PRINT(6,11) X
STOP
END
REAL FUNCTION FUN(X)
FUN=X+TAN(X)
RETURN
END
REAL FUNCTION ANUMINT(FN,ALOW,AHIGH)
EXTERNAL FN
AINC=(AHIGH-ALOW)*0.001
SUM=0.0005*(FN(ALOW)+FN(AHIGH))
DO 7 I=1,999
7 SUM=SUM+FN(ALOW+FLOAT(I)*AINC)
RETURN
END
The versions of FORTRAN IV provided by IBM for the IBM System/360 included some extensions. REAL and DOUBLE PRECISION could be referred to as REAL*4 and REAL*8. COMPLEX*16, allowing complex numbers the real and imaginary parts of which were both double precision, was also one of these extensions.
As well, one could declare a variable to be of CHARACTER*n type, to reserve space for n characters. These variables would usually have to be filled with trailing blanks if they contained a short string, and no explicit character manipulation functions were included in the language, but the A format code, present even in the original FORTRAN language, permitted the input and output of these variables.
The IMPLICIT statement, allowing the first letter rule to be changed, was another extension to FORTRAN IV included on the System/360.
The first FORTRAN IV compiler, the one for the STRETCH, still included the FREQUENCY statement from the original FORTRAN compiler.
Here is an example of a FORTRAN IV program. It includes constants for converting from degrees to radians, and radians to degrees, expressed in internal binary form, which is machine dependent. Also note that it makes use of the assigned GO TO statement, because it repeatedly uses the same one of several alternatives in an inner loop: it is a program to draw a map of the world in one of several projections.
Aside from System/360 machine dependencies, this also calls routines to use an on-line plotter on I/O unit 9 that are peculiar to the particular MTS installation on which it was used: it also tested if it was being run from punched cards or from a terminal, to determine how it would ask for input, again using a routine peculiar to the operating system.
The version of FORTRAN used (or a local addition to its library) allowed free-format I/O, but the compiler did not allow putting an asterisk directly in the I/O statement, although a variable containing an asterisk was what indicated free-format I/O. So, as $ is the shift of * on a keypunch, and this version of FORTRAN allowed $ in variable names even as the first letter, a variable containing only an asterisk was given $ as its name.
Also, it is meant to work with either a CALCOMP plotter whose plotting area is 33 inches wide, or to be used from a Tektronix 4010 display, which is the reason for some of the less obvious portions of the code. It should be immediately obvious that CALL PLOT(X,Y,3) means to plot to point X, Y without drawing (with the pen up) and CALL PLOT(X,Y,2) means to draw to point X, Y from a perusal of the code.
A few comments have been added to the code as it stood originally; otherwise, it is not changed. In addition to an assigned GO TO being used to switch the program to the correct routine to calculate a point for the projection in use, another is used to allow the program to switch from plotting the map to the graticule, and another deals with various possible cases of whether or not a line should be drawn to the current point from the previous point.
This code does not illustrate particularly good programming style, and could thus be categorized as a youthful folly of mine, but it still does illustrate that even in the FORTRAN IV era, the assigned GO TO still can be put to good use shaving cycles from a program.
C THIS IS A PROGRAM TO DRAW MAPS OF THE WORLD
REAL BUF(60),DTR/Z3F477D1B/,RTD/Z42394BB8/
INTEGER FILE(20)
REAL ASPA(12)/-1.,1.,1.5,2.,2.,1.,2.,1.8,0.,0.,0.,0./
INTEGER IBF(58)/58*0/
LOGICAL*1 LIB(232)
INTEGER ITERC/0/
LOGICAL*1 FIAR(44),ICAR(4)
LOGICAL*1 $(1)/1H*/
INTEGER*2 HX,HY
LOGICAL*1 REPL
EQUIVALENCE (LIB,IBF)
EQUIVALENCE (ICAR,ITERC)
ASSIGN 4406 TO IFIRS
CALL PLOTS
CALL GDINF('9 ',FIAR)
ICAR(4)=FIAR(14)
C ITERC IS 2 FOR TERMINAL, 3 FOR FILE
GO TO (90801,90801,90802),ITERC
90801 ASSIGN 272 TO ITCL
ASSIGN 4404 TO ITC2
GO TO 90803
90802 ASSIGN 373 TO ITCL
ASSIGN 4401 TO ITC2
90803 CONTINUE
CALL CREPLY(&875)
REPL=.TRUE.
ASSIGN 575 TO IQIZ
676 WRITE(6,991)
WRITE(6,992)
READ(5,$,END=909)AMR,AAR,AMS
WRITE(6,981)
READ(5,$)PLEN
WRITE(6,971)
WRITE(6,972)
WRITE(6,973)
READ(5,$)IPROJ
WRITE(6,961)
READ(5,$)ILAI,ILOI
WRITE(6,951)
WRITE(6,952)
WRITE(6,953)
READ(5,$)IGTO
GO TO 287
875 ASSIGN 878 TO IQIZ
REPL=.FALSE.
GO TO 878
575 WRITE(6,1901)
878 READ(5,$,END=909)AMR,AAR,AMS,PLEN,IPROJ,ILAI,ILOI,IGTO
287 YCT=.5*PLEN
ASPE=ASPA(IPROJ)
IF (ASPE .GT. 0.0) GO TO 553
IF(REPL)WRITE(6,941)
READ(5,$)ASPE
553 IF(PLEN-33.0)53,53,9999
53 XCT=YCT*ASPE
PWID=XCT+XCT
SCALE=PWID*2.638889E-3
GO TO ITC2,(4401,4404)
4401 GO TO IFIRS,(4400,4406)
4400 IF(IGTO)4404,4404,4402
4402 YCM=YCUM+PLEN
IF(YCM .GT. 33.0) GO TO 4403
CALL PLOT(0.0,PLPR,-3)
XMAX=AMAX1(XMAX,PWID)
YCUM=YCN
GO TO 4404
4406 ASSIGN 4400 TO IFIRS
GO TO 4405
4403 CALL PLOT(XMAX,PLPR-YCUM,-3)
4405 YCUM=PLEN
XMAX=PWID
4404 IGTO=IABS(IGTO)
IF(IGTO-10)4408,4407,4407
4407 IGTO=IGTO-10
IF(REPL)WRITE(6,931)
READ(5,31)FILE
CALL SETLIO('2 ',FILE)
4408 PLPR=PLEN
C INITIALIZATION FOR THE CHOSEN PROJECTION, INCLUDING DRAWING THE
C BORDER OF THE MAP
GO TO (600,601,602,603,604,605,606,607,608,609,610,611),IPROJ
C MERCATOR
600 QTR=DTR*.5
AMX=PLEN*.48
AMH=181.894*ASPE
XXB=180.*SCALE
XXC=XXB+XCT
AXA=AMX+YCT
CALL PLOT(XXC,AXA,3)
XXD=XCT-XXB
CALL PLOT(XXD,AXA,2)
AXB=YCT-AMX
CALL PLOT(XXD,AXB,2)
CALL PLOT(XXC,AXB,2)
CALL PLOT(XXC,AXA,2)
ASSIGN 401 TO IPR
GO TO 167
C AZIMUTHAL EQUIDISTANT
601 RAD=SCALE*180.
CALL PLOT(XCT,YCT+RAD,3)
DO 27 ID=1,360
ANGLE=DTR*FLOAT(ID)
Y=YCT+RAD*COS(ANGLE)
X=XCT+RAD*SIN(ANGLE)
27 CALL PLOT(X,Y,2)
ASSIGN 402 TO IPR
GO TO 167
C SAVARD EGG
602 RAD=SCALE*180.
SRAD=SCALE*120.
CALL PLOT(XCT,YCT+SRAD,3)
DO 57 ID=1,360
ANGLE=DTR*FLOAT(ID)
X=XCT+RAD*SIN(ANGLE)
Y=YCT+SRAD*COS(ANGLE)
57 CALL PLOT(X,Y,2)
ASSIGN 403 TO IPR
GO TO 167
C SINUSOIDAL
603 XMA=180.*SCALE
CALL PLOT(YCT-90.*SCALE,16.5,3)
DO 7631 ID=1,180
ANGLE=FLOAT(ID-90)
7631 CALL PLOT(XCT-XMA*COS(ANGLE*DTR),SCALE*ANGLE+YCT,2)
DO 7632 ID=1,180
ANGLE=FLOAT(90-ID)
7632 CALL PLOT(XCT+XMA*COS(ANGLE*DTR),SCALE*ANGLE+YCT,2)
ASSIGN 404 TO IPR
GO TO 167
C ORTHOGRAPHIC
604 XMH=90.*SCALE
CALL PLOT(XCT,YCT,3)
DO 7641 ID=2,360,2
ANGLE=DTR*FLOAT(ID)
7641 CALL PLOT(XCT+XMH-XMH*COS(ANGLE),XMH*SIN(ANGLE)+YCT,2)
DO 7642 ID=2,360,2
ANGLE=DTR*FLOAT(ID)
7642 CALL PLOT(XCT+XMH*COS(ANGLE)-XMH,XMH*SIN(ANGLE)+YCT,2)
ASSIGN 405 TO IPR
GO TO 167
C LAMBERT AZIMUTHAL EQUAL-AREA
605 RAD=SCALE*180.
SS=.5*DTR
ASSIGN 406 TO IPR
GO TO 167
C HAMMER-AITOFF
606 XSH=SCALE*90.
XMH=XSH+XSH
SS=.5*DTR
XS=127.2792
SF=2.0
CALL PLOT(XCT,XSH+YCT,3)
DO 7661 ID=1,360
ANGLE=DTR*FLOAT(ID)
7661 CALL PLOT(XMH*SIN(ANGLE)+XCT,XSH*COS(ANGLE)+YCT,2)
ASSIGN 407 TO IPR
GO TO 167
C AITOFF EQUAL-AREA
607 SF=1.8
XS=141.4214
C MULTIPLIES BY ROOT 2, TAKING FIXED +/- 90 OF PROJ TO 1/SF FOR VERT
SS=.5*DTR
RAD=SCALE*180.
SRAD=SCALE*100.
DO 7682 IE=1,2
CALL PLOT(XCT+RAD*.4358899,YCT+SRAD*.9,3)
DO 7681 ID=1,100
ANGLE=FLOAT(ID-50)*2.39539E-2
C ARC SINE .9 EQUALS 64.158 DEGREES OR 1.19769515 RADIANS
C ARC SINE .75 EQUALS 48 DEGREES, 35 MINUTES OR .84806208 RAD
7681 CALL PLOT(XCT+RAD*COS(ANGLE),YCT-SRAD*SIN(ANGLE),2)
7682 RAD=-RAD
ALATH=1.197695
7684 ILON=-180
IC=3
ASSIGN 65 TO IQIC
7683 ALON=FLOAT(ILON)
ALAT=ALATH
GO TO 1478
2678 ILON=ILON+1
IF(ILON.LT.180)GO TO 7683
ALATH=-ALATH
IF (ALATH .LT. 0.) GO TO 7684
ASSIGN 408 TO IPR
GO TO 167
C CARDS TO ENSURE LABELS ARE DEFINED FOR FUTURE EXPANSION
608 ASSIGN 409 TO IPR
609 ASSIGN 410 TO IPR
610 ASSIGN 411 TO IPR
611 ASSIGN 412 TO IPR
167 CONTINUE
ASSIGN 82 TO ILAC
IF(ABS(AAR) .LT. .009) GO TO 276
C ROTATIONS UNDER .01 DEG, NOT ALLOWED: IF NO ROTATION OF
C COORDINATES, INITIALIZATION AND DIFFICULT PART OF ROTATION SKIPPED.
AAR=AAR*DTR
CA=COS(AAR)
SA=SIN(AAR)
ASSIGN 86 TO ILAC
276 IF (IGTO-2) 376,99,376
376 ASSIGN 205 TO IPPR
REWIND 2
C THIS STATEMENT READS A RECORD THE FIRST FIVE CHARACTERS OF WHICH GIVE
C THE NUMBER OF POINTS IN A STRETCH OF COASTLINE
476 READ(2,11,END=9099)ICO
IC=3
ASSIGN 85 TO IQIC
C THESE POINTS WILL BE GIVEN ON SUBSEQUENT RECORDS, THIRTY POINTS TO A
C RECORD
C THESE RECORDS HAVE THE FOLLOWING FORMAT:
C SIX SPACES
C THE LATITUDE OF THE FIRST POINT, AS A 16-BIT INTEGER IN TENTHS OF A
C DEGREE, IN A2 FORMAT
C ONE SPACE
C THE LONGITUDE OF THE FIRST POINT, AS A 16-BIT INTEGER IN TENTHS OF A
C DEGREE, IN A2 FORMAT
C ONE SPACE
C DELTA LAT AND DELTA LON, IN TENTHS OF A DEGREE FOR THE REMAINING
C 29 POINTS, IN EXCESS-128 FORM
4 IK=MIN0(ICO,30)
IP=IK+IK-2
IIP=IP*4
IF(IP)476,48,44
C IF ONLY ONE POINT REMAINS TO BE READ, OMIT THE IMPLIED DO
48 READ(2,21)HX,HY
IHX=HX
IHY=HY
BUF(1)=FLOAT(IHX)/10.
BUF(2)=FLOAT(IHY)/10.
GO TO 500
44 READ(2,21)HX,HY,(LIB(I),I=4,IIP,4)
IHX=HX
IHY=HY
BUF(1)=FLOAT(IHX)/10.
BUF(2)=FLOAT(IHY)/10.
DO 7 J=1,IP
7 BUF(J+2)=BUF(J)+FLOAT(IBF(J)-128)/10.
500 IO=IK+IK-1
J=1
17 CONTINUE
ALAT=BUF(J)
ALON=BUF(J+1)
C PROCEED TO PROGRAM TO PLOT POINTS
GO TO 222
205 CONTINUE
IF(J.LE.10)GO TO 17
ICO=ICO-30
GO TO 4
9899 IF(IGTO-1)373,373,99
99 ASSIGN 215 TO IPPR
IMLL=MIN0(-80,-90+ILAI)
IXLL=0-IMLL
ILON=ILOI-180
ALONH=ALON
IC=3
ASSIGN 65 TO IQIC
ILAT=IMLL
420 ALAT=FLOAT(ILAT)
ALON=ALONH
GO TO 222
215 CONTINUE
ILAT=ILAT+1
IF (ILAT.LE.IXLL) GO TO 420
ILON=ILON+ILOI
IF (ILON.LE.180) GO TO 4410
ASSIGN 225 TO IPPR
ILAM=90-ILAI
ILAT=ILAI-90
510 ALAT=FLOAT(ILAT)
ASSIGN 65 TO IQIC
IC=3
ILON=-180
520 ALON=FLOAT(ILON)
ALAT=ALATH
GO TO 222
225 CONTINUE
ILON=ILON+1
IF(ILON.LE.180)GOTO 520
ILAT=ILAT+ILAI
IF(ILAT .LE. ILAM) GO TO 510
GO TO ITCL,(272,373)
272 CALL PLOT(0.0,0.0,-3)
373 GO TO IQIZ(878,676,575)
909 CALL PLOT(0.0,0.0,999)
STOP
9999 WRITE(6.9961)
STOP
222 CONTINUE
C CARDS TO ACTUALLY PLOT POINT FOLLOW.
C ****************************************** 1
C ROTATION OF AXES
ALON=ALON-AMR
C ASSIGNED GO TO USED TO SPEED PROGRAM
GO TO ILAC,(86,82)
86 ALON=ALON*DTR
ALAT=ALAT*DTR
Z=SIN(ALAT)
X=COS(ALAT)
Y=X*SIN(ALON)
X=X*COS(ALON)
ZN=Z*CA-X*SA
XN=X*CA+Z*SA
ALAT=ARSIN(ZN)*RTD
IF(ABS(XN)+ABS(Y)-.002)350,360,360
350 ALON=0.
GO TO 65
360 ALON=ATAN2(Y,XN)*RTD
82 ALON=ALON+AMS
C ANGLES HAVE NOW BEEN ROTATED, AND ARE IN DEGREES.
C THEIR SIGN IS CORRECT, AND USING ATAN2 TO GET ALON
C PREVENTS BLOWUP NEAR 0 OR 90 DEG.
ALON=AMOD(ALON+900.,360.)-180.
C IF AMS IS WITHIN +/- 180. THIS WILL GIVE ANGLE PROPER RANGE.
GO TO IQIC,(65,75,85,95)
C IF DECIDED IN ADVANCE NOT TO PLOT POINT, SKIP BOUNDARY CHECK,
C OR IF FIRST POINT OF RUN, TO BE ALWAYS PLOTTED TO WITH PEN UP.
95 IF (ALON*AFIR.LE.0.) IC=3
75 IF(ABS(ALON-AFIR).GT.100.) IC=3
65 CONTINUE
C ACTUAL PROCEDURE TO PERFORM PROJECTION NOW BEGINS.
GO TO IPR,(401,402,403,404,405,406,407,408,409,410,411,412)
C MERCATOR
401 X=ALON
Y=RTD*ALOG(TAN(QTR*(ALAT+90.)))
IF (ABS(Y)-AMH)660,660,949
C AZIMUTHAL EQUIDISTANT
402 R=90.-ALAT
IF(R.GT.179.8) GO TO 949
ALON=ALON*DTR
Y=R*SIN(ALON)
X=R*COS(ALON)
GO TO 665
C SAVARD EGG
403 ALATA=ABS(ALAT)
ALONA=ABS(ALON)
YZR=ALATA+ALATA*ALATA*ALATA/24300.
X=ALONA*SQRT(8100.-ALATA*ALATA)*1.111111E-2
DELT=1.333333*ALATA-YZR
IF (ALATA .LE. .1) GO TO 1476
RAD=.5*DELT+2.*(8100.-ALATA*ALATA)/DELT
Y-YZR+RAD-SQRT(RAD*RAD-X*X)
6601 X=SIGN(X,ALON)
Y=SIGN(Y,ALAT)
GO TO 660
C CLOSE TO THE EQUATOR, PARABOLAE APPROXIMATE ARCS TO AVOID NUMERICAL PROBLEMS
1476 Y=YZR+DELT*ALONA*ALONA/32400.
GO TO 6601
C SINUSOIDAL
404 Y=ALAT
X=ALON*COS(ALAT*DTR)
GO TO 660
C ORTHOGRAPHIC
405 ALAT=ALAT*DTR
Y=90*SIN(ALAT)
X=SIGN(90.,ALON)+COS(ALAT)*SIN((ABS(ALON)-90.)*DTR)*SIGN(90.*ALON)
ASSIGN 90 TO IQIC
GO TO 665
C LAMBERT AZIMUTHAL EQUAL AREA
406 R=90.-ALAT
IF (R.GT.179.8) GO TO 949
R=180.*SIN(SS*R)
ALON=ALON*DTR
X=R*COS(ALON)
Y=Y*SIN(ALON)
GO TO 665
C HAMMER-AITOFF
407 ALAT=ALAT*DTR
1470 ALONHA=SS*ALON
Z=SIN(ALAT)
X=COS(ALAT)
Y=X*SIN(ALONHA)
X=X*COS(ALONHA)
ALAT=ARSIN(X)*RTD
IF(ABS(Z)+ABS(Y)-.002)881,882,882
881 ALON=0.
GO TO 883
882 ALON=ATAN2(Z,Y)
883 R=XS*SIN(SS*(90.-ALAT))
Y=R*SIN(ALON)
X=SF*R*COS(ALON)
GO TO 660
408 ALAT=ARSIN(.9*SIN(DTR*ALAT))
GO TO 1476
409 CONTINUE
410 CONTINUE
411 CONTINUE
412 CONTINUE
C |||||||||||||||||||||||||||||||||||||||||| 2
C RETURN TO CONVERSION SEGMENT TO PLOT POINT.
949 IC=3
GO TO 999
660 ASSIGN 75 TO IQIC
665 YYO=Y*SCALE+YCT
XXO=X*SCALE+XCT
CALL PLOT(XXO,YYO,IC)
C ****************************************** 1
C RETURN TO POINT CO-ORDINATING EXTERNAL PROGRAM.
IC=2
999 CONTINUE
GO TO IPPR,(205,215,225,2670)
9961 FORMAT(' PLOT TOO LARGE: TALLER THAN 33 IN.')
931 FORMAT(' ENTER NEW MAP FILE NAME, FOLLOWED BY AT LEAST ONE BLANK')
941 FORMAT(' ENTER ASPECT RATIO (WIDTH/HEIGHT) OF PLOT DESIRED.')
951 FORMAT(' ENTER GRATICULE OPTION: 1-MAP ONLY, 2-GRATICULE ONLY,')
952 FORMAT(' 3-MAP AND GRATICULE: MAKE NEGATIVE IF PREVIOUS MAP')
953 FORMAT(' IS TO BE OVERDRAWN,+10 TO RESPECIFY MAP FILE')
961 FORMAT(' ENTER LAT. AND LONG. INCREMENTS FOR GRATICULE')
971 FORMAT(' ENTER PROJECTION NUMBER: 1-MERCATOR, 2-AZIM. EQUIDIST.')
972 FORMAT(' 3-SAVARD EGG,4-SINUSOIDAL,5-ORTHOGRAPHIC')
973 FORMAT(' 6-LAMBERT AZIMUTHAL EQUAL-AREA,7-HAMMER-AITOFF,')
981 FORMAT(' ENTER HEIGHT OF DESIRED MAP')
991 FORMAT(' ENTER MERIDIAN OF ROTATION, AMOUNT OF ROTATION,')
992 FORMAT(' MERIDIAN TO WHICH IT IS ASSIGNED AFTERWARDS,')
1901 FORMAT(' MR/AR/MA:PLEN:PROJ:LATI/LONI:GRATOPS')
11 FORMAT(I5)
21 FORMAT(6X,A2,1X,A2,1X,58A1)
31 FORMAT(20A4)
END
The FORTRAN 66 standard codified FORTRAN IV in an official standard; since FORTRAN IV had been in existence since 1963, however, except in contexts where standards conformance was specified, FORTRAN 66 never really caught on as the name of this form of the language.
Copyright (c) 2007 John J. G. Savard